Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB advanced query: get elements in an array matching a second condition

Tags:

mongodb

We have a collection of elements that has the following structure:

elements:

{
id : 123,
items : [ { color: "blue", "groups" : [3, 5] }, { color: "red", "groups" : [6, 8] } ]
}

{
id : 124,
items : [ { color: "blue", "groups" : [1, 2] }, { color: "green", "groups" : [5, 9] } ]
}

We want an efficient way to get Elements that have an item with color blue accessible to groups 5, 9, 27, 123 or 56. This should return Element with id 123 but not element with id 124 because item must meet both conditions. We want the query to be as efficient as possible.

This query is efficient but does not meet the requirement:

{$and : { "items.groups" : { $in : [5, 9, 27, 123, 56] }, "items.color" : "blue" }} 

as it will match id = 124 because it has an item that matches "blue" and another one that matches group 9.

like image 518
MMind Avatar asked Oct 16 '12 22:10

MMind


People also ask

How do you match an array element in MongoDB?

The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria. If you specify only a single <query> condition in the $elemMatch expression, and are not using the $not or $ne operators inside of $elemMatch , $elemMatch can be omitted.

How do you find documents with a matching item in an embedded array?

Use $match With $eq to Find Matching Documents in an Array in MongoDB. Use $match With $all to Find Matching Documents in an Array in MongoDB.

How do I pull all elements in an array in MongoDB?

The $pullAll operator removes all instances of the specified values from an existing array. Unlike the $pull operator that removes elements by specifying a query, $pullAll removes elements that match the listed values.


1 Answers

You need to use $elemMatch because you're looking to match multiple attributes of a single array element:

db.test.find({ items: { $elemMatch: { 
    color: "blue", 
    groups: { $in: [5, 9, 27, 123, 56] } 
}}});
like image 104
JohnnyHK Avatar answered Sep 30 '22 19:09

JohnnyHK