How to use $elemMatch on aggregate's projection?

Stephen Lynx picture Stephen Lynx · Aug 27, 2014 · Viewed 31.8k times · Source

This is my object:

{ "_id" : ObjectId("53fdcb6796cb9b9aa86f05b9"), "list" : [ "a", "b" ], "complist" : [ { "a" : "a", "b" : "b" }, { "a" : "c", "b" : "d" } ] }

And this is what I want to accomplish: check if "list" contains a certain element and get only the field "a" from the objects on "complist" while reading the document regardless of any of these values. I'm building a forum system, this is the query that will return the details of a forum. I need to read the forum information while knowing if the user is in the forum's white list.

With a find I can use the query

db.itens.find({},{list:{$elemMatch:{$in:["a"]}}})

to get only the first element that matches a certain value. This way I can just check if the returned array is not empty and I know if "list" contains the value I'm looking for. I can't do it on the query because I want the document regardless of it containing the value I'm looking for in the "list" value. I need the document AND know if "list" has a certain value.

With an aggregate I can use the query

db.itens.aggregate({$project:{"complist.a":1}})

to read only the field "a" of the objects contained in complist. This is going to get the forum's threads basic information, I don't want all the information of the threads, just a couple of things.

But when I try to use the query

db.itens.aggregate({$project:{"complist.b":1,list:{$elemMatch:{$in:["a"]}}}})

to try and do both, it throws me an error saying the operator $elemMatch is not valid.

Am I doing something wrong here with the $elemMatch in aggregate? Is there a better way to accomplish this?

Answer

Graeme Pyle picture Graeme Pyle · Apr 15, 2016

For some reason $elemMatch doesn't work in aggregations. You need to use the new $filter operator in Mongo 3.2. See https://docs.mongodb.org/manual/reference/operator/aggregation/filter/