0

Convert shell command to Java code,

Hi what iam trying to do is, GROUP collection by "sourceSystemName" and get values of logID,type,_id,sourceSystemName,logTime for MAX "logTime"

Collection Sample Data:(contains 1million data)

{ "logID" : "1487408645950", "logTime" : ISODate("2017-02-6T06:47:59Z"), "type" : "SYSTEM_MONITOR", "sourceSystemId" :"192.168.1.226", "sourceSystemName" : "LOADER.LOG" }

{ "logID" : "1488226732268", "logTime" : ISODate("2017-02-16T06:48:00Z"),"type" : "SYSTEM_MONITOR", "sourceSystemId" :"192.168.1.226", "sourceSystemName" : "PLATFORM.LOG" }

{ "logID" : "1488293048361", "logTime" : ISODate("2017-02-16T06:48:01Z"),"type" : "SYSTEM_MONITOR", "sourceSystemId" :"192.168.1.226", "sourceSystemName" : "PLATFORM.LOG" }

{ "logID" : "1487496165381", "logTime" : ISODate("2017-02-16T06:48:03Z"),"type" : "SYSTEM_MONITOR", "sourceSystemId" :"192.168.1.226", "sourceSystemName" : "LOADER.LOG" }

Task:

GROUP by "sourceSystemName"

get values of  logID,type,_id,sourceSystemName,logTime for MAX "logTime"

ExpectedOutput:

{ "_id" : "LOADER.LOG", "logTime" : ISODate("2017-02-16T20:44:06Z"), "result" : [ { "sourceSystemName" : "LOADER.LOG", "_id" : ObjectId("58a686bb1a20043138d47ecb"), "logID" : "1488673221443", "type" : "SYSTEM_MONITOR", "logTime" : ISODate("2017-02-16T20:44:06Z") } ] }

{ "_id" : "PLATFORM.LOG", "logTime" : ISODate("2017-02-16T08:42:25Z"), "result" : [ { "sourceSystemName" : "PLATFORM.LOG", "_id" : ObjectId("58a565f61a20041b81aa4017"), "logID" : "1487834117661", "type" : "SYSTEM_MONITOR", "logTime" : ISODate("2017-02-16T08:42:25Z") } ] }

Command used in MongoShell:

 db.log_system_monitoring.aggregate([{
  "$group": {
      "_id": "$sourceSystemName",
      "logTime": {
          "$max": "$logTime"
      },
      "result": {
          "$push": {
              "_id": "$_id",
              "logID": "$logID",
              "type": "$type",
              "logTime": "$logTime"
          }
      }
  }
 }, {
  "$project": {
      "logTime": 1,
      "result": {
          "$setDifference": [{
                  "$map": {
                      "input": "$result",
                      "as": "result",
                      "in": {
                          "$cond": [{
                                  "$eq": ["$logTime", "$$result.logTime"]
                              },
                              "$$result",
                              false
                          ]
                      }
                  }
              },
              [false]
          ]
      }
  }
 }])

now i need to convert this command to java code, the problem is , i dont know how to append $setDifference object to DOCUMENT() object mongodb java driver. can anyone help this,

if there is anyother better solution for this output pls suggest me.

4
  • Please tell us what you have tried so far for us to help you. Commented Feb 20, 2017 at 18:07
  • hi @Veeram i improved my question , suggest some solution for this, Commented Feb 21, 2017 at 10:11
  • What is your mongo server version ? Commented Feb 22, 2017 at 1:04
  • mongodb version 3.2.11 @Veeram Commented Feb 22, 2017 at 5:22

1 Answer 1

1

You can try something like below.

    List<Document> results = 
            collection.aggregate(
        Arrays.asList(
                Aggregates.group(
                        "$sourceSystemName",
                         max("logTime", "$logTime"),
                         push("result",
                                new Document("_id", "$id").
                                        append("logID", "$logID").
                                        append("type", "$type").
                                        append("logTime", "$logTime"))
                ),
                Aggregates.project(
                        fields(include("logTime"),
                                new Document("result",
                                        new Document("$setDifference",
                                                Arrays.asList(
                                                        new Document("$map",
                                                                new Document("input", "$result").
                                                                        append("as", "result").
                                                                        append("in",
                                                                                new Document("$cond",
                                                                                        Arrays.asList(new Document("$eq", Arrays.asList("$logTime", "$$result.logTime")),
                                                                                                "$$result",
                                                                                                false)
                                                                                )
                                                                        )
                                                        ),
                                                        Arrays.asList(false)
                                                )
                                        )
                                )
                        )
                )
        )
 ).into(new ArrayList<>());

OR

String maxResult =  "{\n" +
  "\t\"$setDifference\": [{\n" +
  "\t\t\t\"$map\": {\n" +
  "\t\t\t\t\"input\": \"$result\",\n" +
  "\t\t\t\t\"as\": \"result\",\n" +
  "\t\t\t\t\"in\": {\n" +
  "\t\t\t\t\t\"$cond\": [{\n" +
  "\t\t\t\t\t\t\t\"$eq\": [\"$logTime\", \"$$result.logTime\"]\n" +
  "\t\t\t\t\t\t},\n" +
  "\t\t\t\t\t\t\"$$result\",\n" +
  "\t\t\t\t\t\tfalse\n" +
  "\t\t\t\t\t]\n" +
  "\t\t\t\t}\n" +
  "\t\t\t}\n" +
  "\t\t},\n" +
  "\t\t[false]\n" +
  "\t]\n" +
  "}";

List<Document> results = collection.aggregate(Arrays.asList(Aggregates.group("$sourceSystemName", max("logTime", "$logTime"), push("result", new Document("_id", "$id").
                append("logID", "$logID").
                append("type", "$type").
                append("logTime", "$logTime") )), Aggregates.project(fields(include("logTime"), new Document("result", Document.parse(maxResult)))
 ))).into(new ArrayList<>());

OR better would be to use $filter

String letFilter = "{\n" +
    "\t$let: {\n" +
    "\t\tvars: {\n" +
    "\t\t\tlogTimeMax: {\n" +
    "\t\t\t\t$max: \"$result.logTime\"\n" +
    "\t\t\t}\n" +
    "\t\t},\n" +
    "\t\tin: {\n" +
    "\t\t\t$filter: {\n" +
    "\t\t\t\tinput: \"$result\",\n" +
    "\t\t\t\tas: \"result\",\n" +
    "\t\t\t\tcond: {\n" +
    "\t\t\t\t\t$eq: [\"$$result.logTime\", '$$logTimeMax']\n" +
    "\t\t\t\t}\n" +
    "\t\t\t}\n" +
    "\t\t}\n" +
    "\t}\n" +
    "}";

 List<Document> results = collection.aggregate(Arrays.asList(Aggregates.group("$sourceSystemName", push("result", new Document("_id", "$id").
                        append("logID", "$logID").
                        append("type", "$type").
                        append("logTime", "$logTime") )), Aggregates.project(new Document("result", Document.parse(letFilter)))
        )).into(new ArrayList<>());
Sign up to request clarification or add additional context in comments.

7 Comments

hi @Veeram can you tell me which version of mongodb java driver used for above answer,
I have used 3.4.1. Are you running into issue ?
yes i have some issue push and max shows undefined error .
Sorry. I should have mentioned this in the answer. Those are static imports. Add this import static com.mongodb.client.model.Accumulators.*;
Very big thanks to you buddy, it works for me in mongodb java 3.2 driver also
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.