【问题标题】:Call MongoDB function from Java从 Java 调用 MongoDB 函数
【发布时间】:2015-09-09 12:52:03
【问题描述】:

我正在尝试从 MongoDB Java 驱动程序调用存储的 JavaScript 函数。

我一直按照本指南将函数存储在数据库服务器上,我可以从 mongo shell 调用函数并返回结果。

但是我不知道如何在 Java 中调用相同的函数?

根据这个http://api.mongodb.org/java/current/com/mongodb/DB.html#doEval-java.lang.String-java.lang.Object...-有一个方法叫doEval

我也试过用这个方法:

public static String callFunction() {

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

但是当我调用该方法时,我得到的是:

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

在这种情况下,我希望能找回数字 3。

上述代码的另一个问题是 client.getDB() 方法已被弃用。据我了解,调用的新方法是client.getDatabase(),它返回一个MongoDatabase 对象,但根据API,没有执行函数的方法。

所以我的问题是:是否可以通过 Java 在数据库服务器上执行存储的 JavaScript 函数并取回该函数的结果?如果可能的话,我会很感激一些关于如何做到这一点的帮助?

谢谢。

编辑:

根据Calling server js function on mongodb from java的评论:

"好像getNextSequence是mongo里写的函数 javascript外壳。既不是数据库(mongod)也不是Java端 知道此功能存在,但两者都无法解释 函数包含的 Javascript 代码。您将不得不重新实现它 在爪哇。 "

我试图实现的函数比上面的例子要复杂一些——它应该返回一个文档集合,而使用 db.doEval 方法似乎不起作用。

所以我猜评论是正确的?

【问题讨论】:

    标签: java mongodb


    【解决方案1】:

    您可以使用 java 驱动程序完成所有这些操作。

    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);
    

    结果也是:

    Document{{retval=5.0, ok=1.0}}
    

    【讨论】:

      【解决方案2】:

      你应该这样做:

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

      如果您在 eval 中仅使用函数名,则仅引用服务器端存储函数代码的 JavaScript 变量。它不执行它。当您使用括号时,您请求实际执行一个函数。如果您需要发送比数字更复杂的内容,我建议您使用 JSON 序列化程序。

      【讨论】:

      • 好的,成功了,谢谢。但这并不能完全回答我的问题。正如我所写:方法 client.getDB() 已弃用。据我了解,调用的新方法是 client.getDatabase() ,它返回一个 MongoDatabase 对象,但根据 API,没有执行函数的方法。所以我需要弄清楚这是否使用了不推荐使用的方法/类。
      • 我已经接受了您的回答,因为您确实提供了帮助。但我选择用 Java 实现我的功能。
      • 试试这个:new MongoClient(...).getDatabase(...).runCommand(new BsonDocument("eval", new BsonString("echoFunction(3)"))); .并查看docs.mongodb.org/master/reference/command/eval 了解更多详情。
      • 不要忘记 eval 操作现在已被弃用。所以你切换到java代码是正确的方向(除非在服务器上执行js是实现你需要的唯一方法)。
      • @rsutormin 有没有从 Java 调用函数的选项??
      【解决方案3】:

      我通过以下方式解决了同样的问题:

      我在 mongoShell 中运行一个命令来创建我存储的 JavaScript 函数:

      db.system.js.save(
         {
           _id: "echoFunction" ,
           value : function(x1) { return x1; }
         }
      )
      
      db.system.js.save(
         {
           _id : "myAddFunction" ,
           value : function (x, y){ return x + y; }
         }
      );
      
      
      db.system.js.save(
          {
          _id: "fullFillCollumns" ,
          value : function () { 
              for (i = 0; i < 2000; i++) {
              db.numbers.save({num:i}); } }
          }
      );
      

      要从 MongoDB Java 驱动程序执行此功能:

      MongoClient mongoClient = new MongoClient();
      MongoDatabase db = mongoClient.getDatabase("databaseName");
      
      db.runCommand(new Document("$eval", "fullFillCollumns()"));
      
      Document doc1 = db.runCommand(new Document("$eval", "echoFunction(5)"));
      System.out.println(doc1);
      
      Document doc2 = db.runCommand(new Document("$eval", "myAddFunction(5,8)"));
      System.out.println(doc2); 
      

      我看到集合编号已创建并填充了值。在 IntellijIdea 控制台中,我看到:

      Document{{retval=5.0, ok=1.0}}
      Document{{retval=13.0, ok=1.0}}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-20
        • 2013-11-11
        • 2012-02-07
        • 2017-04-19
        • 1970-01-01
        相关资源
        最近更新 更多