How to use $elemMatch on aggregate's projection?

时光总嘲笑我的痴心妄想 提交于 2019-11-29 17:26:38

问题


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?


回答1:


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/




回答2:


Actually, the simplest solution is to just $unwind your array, then $match the appropriate documents. You can wind-up the appropriate documents again using $group and $push.




回答3:


The answer to this question maybe help.

db.collection_name.aggregate({
    "$match": {
        "complist": {
            "$elemMatch": {
                "a": "a"
            }
        }
    }
});



回答4:


Although the question is old, here is my contribution for November 2017.

I had similar problem and doing two consecutive match operations worked for me. The code below is a subset of my whole code and I changed elements names, so it's not tested. Anyway this should point you in the right direction.

db.collection.aggregate([
    {
        "$match": {
            "_id": "ID1"
        }
    },
    {
        "$unwind": "$sub_collection"
    },
    {
        "$match": {
            "sub_collection.field_I_want_to_match": "value"
        }
    }
])



回答5:


You can use $eq operator with $elemMatch

db.items.find({}, {
  "complist.b": 1,
  "list": { $elemMatch: { $eq: "a" } }
})



回答6:


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.



来源:https://stackoverflow.com/questions/25528217/how-to-use-elemmatch-on-aggregates-projection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!