mongodb 中的数组中是否存在元素的条件投影

Conditional Projection if element exists in Array in mongodb

如果一个值与一个巨大的子数组中的一个值匹配,是否有直接的方法来投影一个新字段。我知道我可以在 $match 条件下使用 $elemMatch 或 $,但这不允许我获得其余的非匹配值(在我的例子中是用户)。

基本上我想列出所有类型 1 的项目并在突出显示订阅用户的同时显示所有用户。我想通过 mongodb 这样做的原因是为了避免为每个项目迭代数千个用户。事实上,这是我问题的第 2 部分,我可以限制用户数组的数量 returned,我只需要大约 10 个数组值 returned 而不是数千个。

集合结构为

   {
     name: "Coke",
     type: 2,
     users:[{user: 13, type:1},{ user:2: type:2}]
    },
    {
     name: "Adidas",
     type: 1,
     users:[{user:31, type:3},{user: 51, type:1}]
     },
    {
     name: "Nike",
     type: 1,
     users:[{user:21, type:3},{user: 31, type:1}]
     }

文档总数超过 200,000 份并且还在增加中... 每个文档有 10,000~50,000 个用户..

预计return

    {
     isUser: true,
     name: "Adidas",
     type: 1,
     users:[{user:31, type:3},{user: 51, type:1}]
     },
    {
     isUser: false,
     name: "Nike",
     type: 1,
     users:[{user:21, type:3},{user: 31, type:1}]
     }

我一直在尝试这个

.aggregate([
            {$match:{type:1}},
            {$project:
                     {
                      isUser:{$elemMatch:["users.user",51]},
                      users: 1,
                      type:1,
                      name: 1
                     }
             }
           ])

这失败了,我得到一个错误 "Maximum Stack size exceeded"。我尝试了很多组合并且 none 似乎有效。我真的很想避免 运行 多次调用 mongodb。这可以在一次调用中完成吗?

有人告诉我使用 unwind,但我有点担心它可能会导致内存问题。

如果我使用 mysql,一个简单的子查询就可以完成工作...我希望我忽略了 mongodb.

中类似的简单解决方案

处理数组元素的条件并使用 $anyElementTrue which evaluates an array as a set and returns true if any of the elements are true and false otherwise, the $ifNull operator will act as a safety net that evaluates the following $map expression and returns the value of the expression if the expression evaluates to a non-null value. The $map in the $ifNull operator is meant to apply the conditional statement expression to each item in the users array and returns an array with the applied results. The resulting array will then be used evaluated by the $anyElementTrue 的组合匹配结果,这最终将计算并 return isUser 每个文档的字段:

db.collection.aggregate([
    { "$match": { "type": 1} },
    {
        "$project": {
            "name": 1, "type": 1,
            "isUser": {
                "$anyElementTrue": [
                    {
                        '$ifNull': [ 
                            {
                                "$map": {
                                    "input": "$users",
                                    "as": "el",
                                    "in": { "$eq": [ "$$el.user",51] }
                                }
                            },
                            [false]
                        ]
                    }
                ]
            }
        }
    }
])