2

I have Collection as following. I have query this collection by user.

 {
      "user": "username",
      "sites": {
        "site": "abc",
        "keywords": [
          {
            "keyword": "keyword1",
            "dailyranks": [
              {
                "fild1": "value1"
              },
              {
                "fild2": "value2"
              },
              {
                "fild3": "value3"
              },
            ]
          },
          {
            "keyword": "keyword2",
            "dailyranks": [
              {
                "fild1": "value1"
              },
              {
                "fild2": "value2"
              },
              {
                "fild3": "value3"
              },  
            ]
          },
        ],
      }
    }

I want to get the result from the collection as follows, I want to get the last elements of keyword array in the collection

[
    {
        "keyword" : "keyword1"
        "fild2" : "value2",
        "fild3" : "value3"
    },
    {
       "keyword" : "keyword2"
        "fild2" : "value2",
        "fild3" : "value3"
    },
]

I have aggregate using $project, but didn't work out. help me to sort this out.

Code used-

BasicDBObject siteObject = new BasicDBObject();
siteObject.append("keywords", "$sites.keywords.keyword");
siteObject.append("lastrank", "$sites.keywords.dailyranks");

BasicDBList aDBList = new BasicDBList();
aaa.add(new BasicDBObject("user", modelLogin.getUSER_NAME()));

ArrayList<BasicDBObject> doc = new ArrayList<>();
doc.add(new BasicDBObject().append("$unwind", "$sites"));
doc.add(new BasicDBObject("$match", aDBList));
 doc.add(new BasicDBObject().append("$project", siteObject));
AggregationOutput output = coll.aggregate(doc);
13
  • Can you show what you've tried so far, with your aggregation and $project? Commented Mar 17, 2017 at 10:14
  • @VinceBowdren question updated with source code thanks Commented Mar 17, 2017 at 10:19
  • But there doesn't seem to be a $project clause in there? Commented Mar 17, 2017 at 10:21
  • sory my bad. I already again. Commented Mar 17, 2017 at 10:23
  • OK; and what output do you get from that? Commented Mar 17, 2017 at 10:33

1 Answer 1

2

You can try below aggregation.

Use $map to transform the Keywords array.

Within $map, use $arrayElemAt to project the last and second last values from dailyranks and $let operator to hold the result from $arrayAtElem and project the fild value.

db.coll.aggregate({
    $project: {
        keywords: {
            $map: {
                input: "$sites.keywords",
                as: "result",
                in: {
                    keyword: "$$result.keyword",
                    fild2: {$let: {vars: {obj: {$arrayElemAt: ["$$result.dailyranks", -2]}},in: "$$obj.fild2"}},
                    fild3: {$let: {vars: {obj: {$arrayElemAt: ["$$result.dailyranks", -1]}},in: "$$obj.fild3"}}
                }
            }
        }
    }
})

Java Equivalent

MongoClient mongoClient = new MongoClient();
MongoDatabase db  = mongoClient.getDatabase("db")
MongoCollection<Document> collection = db.getCollection("collection");
List<Document> results =
    collection.aggregate(
        Arrays.asList(
            Aggregates.match(Filters.eq("user", modelLogin.getUSER_NAME() )),
            Aggregates.project(
                Projections.fields(
                    new Document("keywords",
                        new Document("$map",
                        new Document("input", "$sites.keywords").
                        append("as", "result").
                        append("in",
                            new Document("keyword","$$result.keyword").
                                append("fild2",
                                    new Document("$let",
                                    new Document("vars", new Document("obj",
                                            new Document("$arrayElemAt", Arrays.asList("$$result.dailyranks", -2)))).
                                    append("in", "$$obj.fild2" ))).
                                append("fild3",
                                    new Document("$let",
                                    new Document("vars", new Document("obj",
                                            new Document("$arrayElemAt", Arrays.asList("$$result.dailyranks", -1)))).
                                    append("in", "$$obj.fild3" )))
                            )
                        )
                    )))
        )).into(new ArrayList<>());
Sign up to request clarification or add additional context in comments.

9 Comments

@veerram what is the purpose of " fields" in Aggregates.project(). got comping error
It's use to project the values. Updated. More here mongodb.github.io/mongo-java-driver/3.4/javadoc/?com/mongodb/…
got compile error like this, no suitable method found for aggregate(List<Bson>) method DBCollection.aggregate(DBObject,DBObject...) is not applicable
What is your mongo java driver version ?
it is 3.3.0. I just update it to 3.4 but still getting the same error
|

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.