Skip to main content

馃憪 Searching inside Objects in arrays

In our books, we're using the Attribute Pattern to have different attributes in our documents. As we can see in the sample doc, we have an attributes array, containing several objects, each with the same structure:

attributes: [
{
key: 'edition',
value: '1st'
},
{
key: 'dimensions',
value: 'Height: 1.111 Inches, Length: 1.111 Inches, Weight: 0.2 Pounds, Width: 1.111 Inches'
},
{
key: 'isbn13',
value: '9780765342508'
},
{
key: 'msrp',
value: 6.99
},
{
key: 'isbn',
value: '0765342502'
},
{
key: 'isbn10',
value: '0765342502'
}
],

How do we search for all the books that have an msrp of 9.99? We want books that, inside attributes, have an object with key msrp and value 9.99. We can get it to work with this:

[
{ $unwind : "$attributes" },
{ $match: {"attributes.key": "msrp", "attributes.value": 9.99} },
{ $project: {title: 1, attributes: 1} }
]

Here we're getting a copy of each book for each object inside the $attributes array. This "flattens" the array and returns many copies of the same documents, one for each different attribute that we have which will be different for each of these generated docs.

馃憪 To better understand $unwind, run this aggregation.

You need to select the books collection.

[
{ $match: {_id: "0395623650"} },
{ $unwind : "$attributes" },
]

You should get one document per attribute of the original book. All fields in these returned documents should be the same, except the ones in attributes.

But you can actually match documents in an array in a more straightforward fashion:

[
{ $match: {"attributes.key": "msrp", "attributes.value": 9.99} },
{ $project: {_id: 0, title: 1, year: 1, totalInventory: 1, available: 1, "attributes": 1} }
]