How to execute MongoDB native query (JSON) using mongo-java-driver only?
Asked Answered
B

4

6

How to fire mongo native queries using java-mongo-driver only.

No Spring-Data or EclipseLink or Hibernate OGM, Only using java-mongo-driver

Sample query :

db.orders.aggregate([
   {
      $unwind: "$specs"
   },
   {
      $lookup:
         {
            from: "inventory",
            localField: "specs",
            foreignField: "size",
            as: "inventory_docs"
        }
   },
   {
      $match: { "inventory_docs": { $ne: [] } }
   }
])
Bolognese answered 3/11, 2017 at 10:30 Comment(2)
From offical documentation: mongodb.github.io/mongo-java-driver/3.5/driver/tutorials/…Butterfingers
Are you asking how to express that above aggregate operation using the Java driver? Or are you asking if you can pass the above string into the Java driver and have the driver execute it?Rand
R
4

If your question is:

Can I pass the above string into the Java driver and have the driver execute it?

Then you could use the db.eval command. For example:

MongoDatabase database = mongoClient.getDatabase("...");

Bson command = new Document("eval", "db.orders.aggregate([\n" +
        "   {\n" +
        "      $unwind: \"$specs\"\n" +
        "   },\n" +
        "   {\n" +
        "      $lookup:\n" +
        "         {\n" +
        "            from: \"inventory\",\n" +
        "            localField: \"specs\",\n" +
        "            foreignField: \"size\",\n" +
        "            as: \"inventory_docs\"\n" +
        "        }\n" +
        "   },\n" +
        "   {\n" +
        "      $match: { \"inventory_docs\": { $ne: [] } }\n" +
        "   }\n" +
        "])");
Document result = database.runCommand(command);

But ... the db.eval command is deprecated and its usage is not advised. The MongoDB Java driver can be used to execute your aggregation but not in its 'string form', instead you would use the Java driver's aggregation helpers to create a Java form of your aggregation command. Plenty of details on this in the docs.

Here's an (untested) example using a 3.x MongoDB Java Driver ...

MongoCollection<Document> collection = mongoClient.getDatabase("...").getCollection("...");

AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
        // the unwind stage
        new Document("$unwind", "$specs"),

        // the lookup stage
        new Document("$lookup", new Document("from", "inventory")
                .append("localField", "specs")
                .append("foreignField", "size")
                .append("as", "inventory_docs")),

        // the match stage
        new Document("$match", new Document("inventory_docs", new BasicDBObject("$ne", new String[0])))
));

.. this might help you to see the form of translation from shell script to Java.

Rand answered 3/11, 2017 at 11:54 Comment(0)
B
3

I was running out of time so used following workaround. Will explore Morcos suggestion in detail later. But following code also works.

import com.infrasoft.mongo.MongoClientFactory;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;

/**
 *
 * @author charudatta.joshi
 */
public class TestNaiveQuery1 {

    public static void main(String[] args) {

        String nativeQuery = "db.orders.aggregate([\n"
                + "   {\n"
                + "      $unwind: \"$specs\"\n"
                + "   },\n"
                + "   {\n"
                + "      $lookup:\n"
                + "         {\n"
                + "            from: \"inventory\",\n"
                + "            localField: \"specs\",\n"
                + "            foreignField: \"size\",\n"
                + "            as: \"inventory_docs\"\n"
                + "        }\n"
                + "   },\n"
                + "   {\n"
                + "      $match: { \"inventory_docs\": { $ne: [] } }\n"
                + "   }\n"
                + "])";

        DBObject command = new BasicDBObject();
        DB db = MongoClientFactory.getMongoClientFactory().getMongoClient().getDB("frms_data_demo");

        nativeQuery = "function() { return (" + nativeQuery + ").toArray(); }";

        //command.put("eval", "function() { return db." + collectionName + ".find(); }");
        command.put("eval", nativeQuery);
        CommandResult result = db.command(command);

        BasicDBList dbObjList = (BasicDBList) result.toMap().get("retval");

        DBObject dbo0 = (BasicDBObject) dbObjList.get(0);
        DBObject dbo1 = (BasicDBObject) dbObjList.get(0);

        System.out.println(dbObjList.get(0));
        System.out.println(dbObjList.get(1));
        // .... just loop on dbObjList

    }


}
Bolognese answered 3/11, 2017 at 13:58 Comment(0)
F
1

this query Deprecated since version 3.0. https://docs.mongodb.com/manual/reference/method/db.eval/ ,i used mongodb4.0 cluster ,not support eval function,

Fatsoluble answered 21/5, 2020 at 9:34 Comment(2)
Is there any other way to solve it,Thanks!@Charudatta JoshiFatsoluble
come up with code samples. Before posting the questions here please learn how to ask the question to get the assured answer. Refer this: stackoverflow.com/help/how-to-askKernan
B
0

@aaronwang4love You can try below code. Not tested. Don't have access to environment now. Please update if it works.

BasicDBObject query = BasicDBObject.parse("{userId: {$gt: \"1\"}}"); 
FindIterable<Document> dumps = crapCollection.find(query);


OR You can Also use com.mongodb.util.JSON

DBObject dbObject = (DBObject)JSON.parse("{userId: {$gt: \"1\"}}");
Bolognese answered 27/5, 2020 at 11:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.