Finding documents containing an array of objects

I have documents of the form:
{a: [ { b: 1, c: 2 }, { b: 3, c: 4 } ]}

I need to find all documents that match a given b and c value in the same nested object. How can I do that? And what is the shape of the index?

I can only figure out a find that automatically enumerates the array in a, and the result is incorrect:

test> db.hx2a.findOne({"$and":[{“a.b”:{"$eq":1}},{“a.c”:{"$eq":4}}]})
{
_id: ObjectId(“62c45959c5da24a18acfa3e8”),
a: [ { b: 1, c: 2 }, { b: 3, c: 4 } ]
}

The values are in two different nested objects, not in the same one.
Thanks!

Take a look at $elemMatch.

Ah fantastic, thanks, Steve!

One more question, I am creating the index the following simple way:

{“a.b”: 1, “a.c”: 1}

My understanding is that it creates an index with a size which is quadratic as a function of the average array size (as the cartesian product is calculated). If true, this is an issue. I did not see anything equivalent to $elemMatch in the operators allowed in partialFilterExpression, is there something that could help, while ensuring that the find leverages the index properly and does not do a full scan?

Thanks again!

If index size with a.b:1,a.c:1 is an issue, I would investigate by using only a.b:1 or a.c:1. The size would be smaller. The field with the highest number of different values will probably provide better performance. For example, if a.b is boolean and a.c is date, a.c index will be more selective.

Understood, it makes sense.
I am thinking also of concatenating b and c in a single field.
Thanks a lot!

1 Like