Search code examples
mongodbprojection

How to use $elemMatch on aggregate's projection?


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?


Solution

  • Well, it happens you can use "array.field" on a find's projection block.

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

    did what I needed.