Skip to content

Instantly share code, notes, and snippets.

@chetanmeh
Last active January 16, 2017 09:56
Show Gist options
  • Save chetanmeh/836ca8fffc4c410daed2 to your computer and use it in GitHub Desktop.
Save chetanmeh/836ca8fffc4c410daed2 to your computer and use it in GitHub Desktop.
Utility JS function for Mongo when used with Jackrabbit Oak

Following js file can be load at start of mongo shell and then the functions can be accessed

$ wget https://gist.githubusercontent.com/chetanmeh/836ca8fffc4c410daed2/raw/oak-mongo.js
$ mongo localhost/oak --shell oak-mongo.js
MongoDB shell version: 2.6.3
connecting to: localhost/oak
type "help" for help
> oak.countChildren('/oak:index/')
356787
> oak.getChildStats('/oak:index')
{ "count" : 356788, "size" : 127743372, "simple" : "121.83 MB" }
> oak.getChildStats('/')
{ "count" : 593191, "size" : 302005011, "simple" : "288.01 MB" }
>
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var oak = (function(global){
"use strict";
var api,
version = "1.0";
api = function(){
return api.version();
};
/*
* Print the current version
*/
api.version = function () {
return print('Oak Mongo helpers : ' + version);
};
api.indexStats = function () {
var result = [];
var totalCount = 0;
var totalSize = 0;
db.nodes.find({'_id': /^2\:\/oak\:index\//}, {_id: 1}).forEach(function (doc) {
var stats = api.getChildStats(api.pathFromId(doc._id));
stats.id = doc._id;
result.push(stats);
totalCount += stats.count;
totalSize += stats.size;
});
result.push({id: "summary", count: totalCount, size: totalSize, "simple": this.humanFileSize(totalSize)});
return result;
};
/**
* Determines the number of child node (including all sub tree)
* for a given parent node path. This would be faster compared to
* {@link getChildStats} as it does not load the doc and works on
* index only.
*
* Note that there might be some difference between db.nodes.count()
* and countChildren('/') as split docs, intermediate docs are not
* accounted for
*
* @param path
* @returns {number}
*/
api.countChildren = function(path){
var depth = this.pathDepth(path);
var totalCount = 0;
while (true) {
var count = db.nodes.count({_id: this.pathFilter(depth++, path)});
if( count == 0){
break;
}
totalCount += count;
}
return totalCount
}
/**
* Provides stats related to number of child nodes
* below given path or total size taken by such nodes
*
* @param path
* @returns {{count: number, size: number}}
*/
api.getChildStats = function(path){
var count = 0;
var size = 0;
this.forEachChild(path, function(doc){
count++;
size += Object.bsonsize(doc);
});
return {"count" : count, "size" : size, "simple" : this.humanFileSize(size)};
};
api.forEachChild = function(path, callable) {
var depth = this.pathDepth(path);
while (true) {
var cur = db.nodes.find({_id: this.pathFilter(depth++, path)});
if(!cur.hasNext()){
break;
}
cur.forEach(callable);
}
};
api.pathFilter = function (depth, prefix){
return new RegExp("^"+ depth + ":" + prefix)
};
api.pathDepth = function(path){
if(path == '/'){
return 0;
}
var depth = 0;
for(var i = 0; i < path.length; i++){
if(path.charAt(i) == '/'){
depth++;
}
}
return depth;
};
api.pathFromId = function(id) {
var index = id.indexOf(':');
return id.substring(index + 1);
};
//http://stackoverflow.com/a/20732091/1035417
api.humanFileSize = function (size) {
var i = Math.floor( Math.log(size) / Math.log(1024) );
return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
};
return api;
}(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment