mongodb 如何在聚合投影上使用 $elemMatch?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25528217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:08:11  来源:igfitidea点击:

How to use $elemMatch on aggregate's projection?

mongodbprojection

提问by Stephen Lynx

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.

这就是我想要完成的:检查“list”是否包含某个元素,并在阅读文档时只从“complist”上的对象中获取字段“a”,而不管这些值中的任何一个。我正在构建一个论坛系统,这是将返回论坛详细信息的查询。我需要阅读论坛信息,同时知道用户是否在论坛的白名单中。

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.

仅读取 complist 中包含的对象的字段“a”。这将获得论坛线程的基本信息,我不想要线程的所有信息,只需要一些东西。

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.

要尝试同时执行这两项操作,它会向我抛出一个错误,指出运算符 $elemMatch 无效。

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

我在这里用 $elemMatch 做错了什么吗?有没有更好的方法来实现这一点?

采纳答案by Stephen Lynx

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

好吧,碰巧您可以在查找的投影块上使用“array.field”。

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

did what I needed.

做了我需要的。

回答by Graeme Pyle

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/

出于某种原因, $elemMatch 在聚合中不起作用。您需要在 Mongo 3.2 中使用新的 $filter 运算符。请参阅https://docs.mongodb.org/manual/reference/operator/aggregation/filter/

回答by Graeme Pyle

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.

实际上,最简单的解决方案是 $unwind 您的数组,然后 $match 相应的文档。您可以使用 $group 和 $push 再次结束适当的文档。

回答by Hevelson Rosario

The answer to this questionmaybe help.

这个问题的答案可能会有所帮助。

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

回答by Paulo Pedroso

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

虽然这个问题很老,但这是我 2017 年 11 月的贡献。

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"
        }
    }
])

回答by Kolomiets Yaroslav

You can use $eqoperator with $elemMatch

您可以将$eq运算符与 $elemMatch 一起使用

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