如何在$ project内部使用过滤器内部数组使用聚合

发布于 2025-01-31 15:05:30 字数 2589 浏览 4 评论 0原文

目前,我正在使用mongoDB存储有关我的表格和响应的数据,当我在集合中使用查找时,返回以下数据:

[
    {
        "_id": 1,
        "forms": [
            {
                "current_version": 0,
                "history": [
                    {
                        "content": [{"label": "vrau"}],
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 2, "response": [{"field": "vrau2"}]},
                            {"client_id": 2, "response": [{"field": "vrau2"}]},
                        ],
                    }
                ],
            }
        ],
        "name": "Testing",
    },
    {
        "_id": 2,
        "forms": [
            {
                "current_version": 1,
                "history": [
                    {
                        "content": [{"label": "vrau"}],
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau11"}]},
                            {"client_id": 1, "response": [{"field": "vrau11"}]},
                            {"client_id": 2, "response": [{"field": "vrau22"}]},
                            {"client_id": 2, "response": [{"field": "vrau22"}]},
                        ],
                    }
                ],
            }
        ],
        "name": "Testing2",
    },
]

我要做的是仅返回第一个文档中的响应:_id _id = 1其中client_id等于1。因此,以下输出是我想要的。

[{
        "_id": 1,
        "forms": [
            {
                "history": [
                    {
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                        ],
                    }
                ],
            }
        ]
    }]

但是我的查询是返回表单字段空的,这是我要做的:

collection.aggregate([
        {
           "$match" : {
               "_id" : 1,
           }
        },
        {
          "$project": {
             "forms": {
                "$filter": {
                   "input": "$forms",
                   "as": "form",
                   "cond": { "$and":[
                       {"$eq": [ "$$form.history.responses.client_id", 1 ]}
                       ]
                   }
                }
             }
          }
        }
    ])

上面的代码出了什么问题?

Currently I'm using mongodb to store data about my forms and responses, when I using a find in my collection the following data is returned:

[
    {
        "_id": 1,
        "forms": [
            {
                "current_version": 0,
                "history": [
                    {
                        "content": [{"label": "vrau"}],
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 2, "response": [{"field": "vrau2"}]},
                            {"client_id": 2, "response": [{"field": "vrau2"}]},
                        ],
                    }
                ],
            }
        ],
        "name": "Testing",
    },
    {
        "_id": 2,
        "forms": [
            {
                "current_version": 1,
                "history": [
                    {
                        "content": [{"label": "vrau"}],
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau11"}]},
                            {"client_id": 1, "response": [{"field": "vrau11"}]},
                            {"client_id": 2, "response": [{"field": "vrau22"}]},
                            {"client_id": 2, "response": [{"field": "vrau22"}]},
                        ],
                    }
                ],
            }
        ],
        "name": "Testing2",
    },
]

What I'm trying to do is return only the responses from the first document: _id = 1 where the client_id is equal to 1. so, the following output is what I want.

[{
        "_id": 1,
        "forms": [
            {
                "history": [
                    {
                        "responses": [
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                            {"client_id": 1, "response": [{"field": "vrau1"}]},
                        ],
                    }
                ],
            }
        ]
    }]

but my query Is returning the forms field empty, this is what I'm trying to do:

collection.aggregate([
        {
           "$match" : {
               "_id" : 1,
           }
        },
        {
          "$project": {
             "forms": {
                "$filter": {
                   "input": "$forms",
                   "as": "form",
                   "cond": { "$and":[
                       {"$eq": [ "$form.history.responses.client_id", 1 ]}
                       ]
                   }
                }
             }
          }
        }
    ])

What is wrong with the code above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

老娘不死你永远是小三 2025-02-07 15:05:30

一种方法是使用$降低将您的多级数组“弄平”到一个响应中。然后,全部剩下的就是$ filter您需要的响应:

db.collection.aggregate([
  {$match: {_id: 1}},
  {
    $project: {
      responses: {
        $reduce: {
          input: "$forms",
          initialValue: [],
          in: {
            $concatArrays: [
              {
                $reduce: {
                  input: "$this.history",
                  initialValue: [],
                  in: {$concatArrays: ["$value", "$this.responses"]}
                }
              },
              "$value"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      responses: {
        $filter: {
          input: "$responses", as: "item", cond: {$eq: ["$item.client_id", 1]}
        }
      }
    }
  }
])

playground示例

One way to do it is to use $reduce to "flatten" your multi level arrays into one array of responses. Then, all is left is to $filter the responses you need:

db.collection.aggregate([
  {$match: {_id: 1}},
  {
    $project: {
      responses: {
        $reduce: {
          input: "$forms",
          initialValue: [],
          in: {
            $concatArrays: [
              {
                $reduce: {
                  input: "$this.history",
                  initialValue: [],
                  in: {$concatArrays: ["$value", "$this.responses"]}
                }
              },
              "$value"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      responses: {
        $filter: {
          input: "$responses", as: "item", cond: {$eq: ["$item.client_id", 1]}
        }
      }
    }
  }
])

Playground example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文