Question

I need to get a list of chunks after sharding inside my Java code. My code is simple and looks like this:

Mongo m = new Mongo( "localhost" , 27017 );

DB db = m.getDB( "admin" );

Object cr = db.eval("db.printShardingStatus()", 1);

A call of eval() returns an error:

Exception in thread "main" com.mongodb.CommandResult$CommandFailure: command failed [$eval]: { "serverUsed" : "localhost/127.0.0.1:27017" , "errno" : -3.0 , "errmsg" : "invoke failed: JS Error: ReferenceError: printShardingStatus is not defined src/mongo/shell/db.js:891" , "ok" : 0.0}
    at com.mongodb.CommandResult.getException(CommandResult.java:88)
    at com.mongodb.CommandResult.throwOnError(CommandResult.java:134)
    at com.mongodb.DB.eval(DB.java:340)
    at org.sm.mongodb.MongoTest.main(MongoTest.java:35)

And, really, if we look into the code of db.js, in line 891 there is a call to a method printShardingStatus() that is not defined inside a file. Inside of sh.status() method in utils_sh.js file, there is even a comment:

// TODO: move the actual commadn here

Important to mention, when I run these commands in mongo command line, everything works properly!

My questions are:

  • Is there any other possibility of getting a full sharding status within Java code? (eg. with DB.command() method)
  • If not, any other suggestions how to avoid my problem?
Was it helpful?

Solution

Many of the shell's helper functions are not available for server-side code execution. In the case of printShardingStatus(), it makes sense because there isn't a console to use for printing output and you'd rather have a string returned. Thankfully, you should be able to pull up the source of the shell function and reimplement it in your application (e.g. concatenating a returned string instead of printing directly).

$ mongo
MongoDB shell version: 2.2.0
connecting to: test
> db.printShardingStatus
function (verbose) {
    printShardingStatus(this.getSiblingDB("config"), verbose);
}

So, let's look at the printShardingStatus() function...

> printShardingStatus
function (configDB, verbose) {
    if (configDB === undefined) {
        configDB = db.getSisterDB("config");
    }
    var version = configDB.getCollection("version").findOne();

    // ...
}

Before turning all of the output statements into string concatenation, you'd want to make sure the other DB methods are all available to you. Performance-wise, I think the best option is to port the innards of this function to Java and avoid server-side JS evaluation altogether. If you dive deeper into the printShardingStatus() function, you'll see it's just issuing find() on the config database along with some group() queries.

If you do want to stick with evaluating JS and would rather not keep this code within your Java application, you can also look into storing JS functions server-side.

OTHER TIPS

Have you deployed a shard cluster properly? If so, you could connect to a mongo database that has sharding enabled.

Try calling the method db.printShardingStatus() with a that database within the mongo shell and see what happens.

Apparently the Javascript function 'printShardingStatus' is only available for the mongo shell and not for execution with server commands, to see the code start mongo.exe and type only 'printShardingStatus' and press enter.

In this case writing an extension method would be the best for solving this...

Javascript way of printing output of MongoDB query to a file

1] create a javascript file

test.js

cursor = db.printShardingStatus();
while(cursor.hasNext()){
    printjson(cursor.next());
}

2] run

mongo admin --quiet test.js > output.txt
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top