Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call MongoDB function from Java

Tags:

java

mongodb

I'm trying to call a stored JavaScript function from the MongoDB Java driver.

I have been following this guide to store the function on the DB server and I'm able to call the function from the mongo shell and have the result returned.

However I cannot figure out how to call the same function in Java?

According to this http://api.mongodb.org/java/current/com/mongodb/DB.html#doEval-java.lang.String-java.lang.Object...- there's a method called doEval

I have also tried to use it with this method:

public static String callFunction() {

    try (MongoClient client = new MongoClient("localhost")) {
        com.mongodb.DB db = client.getDB("TestDB");
        return db.doEval("echoFunction", 3).toString();
    }
}

But when I call the method this is what I get:

{ "retval" : { "$code" : "function (x) {\n    return x;\n}"} , "ok" : 1.0}

and I would expect to get the number 3 back in this case.

Another problem with the above code is that the method client.getDB() is deprecated. As I understand it the new method to call is client.getDatabase() and it returns a MongoDatabase object, but according to the API there is no method to execute a function.

So my question is: Is it possible to execute a stored JavaScript function on the database server from Java and get back the result of that function? And if it is possible, I would appreciate some help on how to do it?

Thank you.

Edit:

According to a comment on Calling server js function on mongodb from java:

"It seems like getNextSequence is a function written in the mongo javascript shell. Neither the database (mongod) nor the Java side knows this function exists and neither is able to interprete the Javascript code the function contains. You will have to reimplement it in Java. "

The function I'm trying to implement is a bit more complex than the example above - it's supposed to return a collection of documents and that does not seems to be working using the db.doEval method.

So I guess the comment is correct?

like image 665
Emil C Avatar asked Sep 09 '15 12:09

Emil C


2 Answers

You can do all this with java driver.

MongoClient mongoClient = new MongoClient();
MongoDatabase mdb = mongoClient.getDatabase("TestDB");

/* run this <code snippet> in bootstrap */
BsonDocument echoFunction = new BsonDocument("value",
        new BsonJavaScript("function(x1) { return x1; }"));

BsonDocument myAddFunction = new BsonDocument("value",
        new BsonJavaScript("function (x, y){ return x + y; }"));

mdb.getCollection("system.js").updateOne(
        new Document("_id", "echoFunction"),
        new Document("$set", echoFunction),
        new UpdateOptions().upsert(true));

mdb.getCollection("system.js").updateOne(
        new Document("_id", "myAddFunction"),
        new Document("$set", myAddFunction),
        new UpdateOptions().upsert(true));

mdb.runCommand(new Document("$eval", "db.loadServerScripts()"));
/* end </code snippet> */

Document doc1 = mdb.runCommand(new Document("$eval", "echoFunction(5)"));
System.out.println(doc1);

The result is also:

Document{{retval=5.0, ok=1.0}}
like image 102
Vinicius Gardênio G Rodrigues Avatar answered Sep 30 '22 15:09

Vinicius Gardênio G Rodrigues


You should do this instead:

        return db.doEval("echoFunction(3)").toString();

If you use just function name in eval you only refer to JavaScript variable on server side storing code of function. It doesn't execute it. When you use parentheses you request to actually execute a function. If you need to send something more complex than a number I would advise to use JSON serializer.

like image 33
rsutormin Avatar answered Sep 30 '22 15:09

rsutormin