简体   繁体   中英

Using java driver to match only if array contains a value equal to another embedded field

I am a beginner at MongoDB. In a pipeline my collection contains documents:

Document{{_id=1, AnyLikes=[2, 3, 4], ILikes=Document{{_id=2}}, TwoLikes=Document{{_id=1}}}}
Document{{_id=1, AnyLikes=[2, 3, 4], ILikes=Document{{_id=2}}, TwoLikes=Document{{_id=3}}}}
Document{{_id=1, AnyLikes=[2, 3, 4], ILikes=Document{{_id=2}}, TwoLikes=Document{{_id=4}}}}

I want to filter only those where AnyLikes contains an element equal to the _id of the TwoLikes document. So for the above it should return only the second and third documents. I tried:

persons.aggregate(asList(match(elemMatch("AnyLikes", eq("$TwoLikes._id")))));

Any idea why it is not working? I get no results.

//actual code output from Mongo Shell
> db.version();
4.2.6
//sample data, used 1,3,4 to simplyfy vlaues for TwoLikes
> db.docs.find();
{ "_id" : 1, "stage" : 1, "AnyLikes" : [ 2, 3, 4 ], "ILikes" : "_id=2", "TwoLikes" : 1 }
{ "_id" : 2, "stage" : 1, "AnyLikes" : [ 2, 3, 4 ], "ILikes" : "_id=2", "TwoLikes" : 3 }
{ "_id" : 3, "stage" : 1, "AnyLikes" : [ 2, 3, 4 ], "ILikes" : "_id=2", "TwoLikes" : 4 }
//flatten the array using $unwind
> db.docs.aggregate([
... {$unwind:"$AnyLikes"},
... {$project:{_id:1,
...            stage:1,
...            AnyLikes:1,
...            TwoLikes:1,
...            matchChk:
...            {
...                $cond:{if:{$eq:["$AnyLikes","$TwoLikes"]},then: "Elem Matched", else:"Elem Not Matched"}
...            }
...    }
...   }
... ]);
{ "_id" : 1, "stage" : 1, "AnyLikes" : 2, "TwoLikes" : 1, "matchChk" : "Elem Not Matched" }
{ "_id" : 1, "stage" : 1, "AnyLikes" : 3, "TwoLikes" : 1, "matchChk" : "Elem Not Matched" }
{ "_id" : 1, "stage" : 1, "AnyLikes" : 4, "TwoLikes" : 1, "matchChk" : "Elem Not Matched" }
{ "_id" : 2, "stage" : 1, "AnyLikes" : 2, "TwoLikes" : 3, "matchChk" : "Elem Not Matched" }
{ "_id" : 2, "stage" : 1, "AnyLikes" : 3, "TwoLikes" : 3, "matchChk" : "Elem Matched" }
{ "_id" : 2, "stage" : 1, "AnyLikes" : 4, "TwoLikes" : 3, "matchChk" : "Elem Not Matched" }
{ "_id" : 3, "stage" : 1, "AnyLikes" : 2, "TwoLikes" : 4, "matchChk" : "Elem Not Matched" }
{ "_id" : 3, "stage" : 1, "AnyLikes" : 3, "TwoLikes" : 4, "matchChk" : "Elem Not Matched" }
{ "_id" : 3, "stage" : 1, "AnyLikes" : 4, "TwoLikes" : 4, "matchChk" : "Elem Matched" }
>

The following works. This is more efficient than @Mailik because it does not do an unwind.

Bson query = new Document().append("$in",asList("$TwoLikes._id", "$AnyLikes"));
persons.aggregate(asList(match(expr(query))));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM