【问题标题】:Aggregation $filter is not working after $lookup$lookup 后聚合 $filter 不起作用
【发布时间】:2021-09-30 15:25:44
【问题描述】:

我试图在查找运算符之后过滤数据。我没有从我的查询中得到预期的行为。

我的网关收藏是

{ "_id" : "18001887", "mac_id" : "18001887", group_id: "0" }
{ "_id" : "18001888", "mac_id" : "18001888", group_id: "1" }
{ "_id" : "18001889", "mac_id" : "18001889", group_id: "0" }

我的命令集合是

{
    "_id" : ObjectId("615581dcb9ebca6c37eb39e4"),
    "org_id" : 0,
    "mac_id" : "18001887",
    "config" : {
        "user_info" : [ 
            {
                "user_id" : 1,
                "user_pwd" : "123456",
                "mapped_id" : 1
            }, 
            {
                "user_id" : 2,
                "user_pwd" : "123123",
                "mapped_id" : 3
            }
        ]
    }
}

{
    "_id" : ObjectId("615581dcb9ebca6c37eb39e4"),
    "org_id" : 0,
    "mac_id" : "18001889",
    "config" : {
        "slave_id" : 1 
    }
}

我想获取 group_id = 0 和 "config.user_info.mapped_id" = 1 的网关命令。 我写了下面的查询,但它似乎不起作用

gateway_model.aggregate([
            {
                $match: {
                    group_id: "0"
                },
                
            },
            {
                $project: {
                    _id: 0,
                    mac_id: 1
                }
            },
            {
                $lookup: {
                    from: "commands",
                    localField: "mac_id",
                    foreignField: "mac_id",
                    as: "childs"
                    
                }
            },
            { 
                $project: {
                    mac_id: 1,
                    childs: {
                        $filter: {
                            "input": "$childs",
                            "as": "child",
                            "cond": {"$eq": ["$$child.config.user_info.mapped_id", 1]},
                        }
                    }
                }
            }
        ])

以上查询返回 group_id 为 0 且 childs 为空数组的网关。

【问题讨论】:

  • 这就是它应该如何工作的。 $filter 运算符将返回一个数组,其中包含与cond 匹配的任何元素。如果没有匹配,则数组将为空。
  • 但是在这种情况下有一个child.config.user_info.mapped_id = 1。检查命令集合示例。我使用的是相同的数据。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

user_info 字段是数组,您正在检查$filter 操作中的等于条件,您可以按照以下方式更改您的$filter 条件,

  • 当我们从数组字段$$child.config.user_info.mapped_id访问mapped_id时,它会返回id数组,所以我们需要使用$in条件
  • $ifNull 检查user_info 字段是否不存在,然后它将返回空白数组
  • 要检查的$in 运算符在mapped_id 的数组中为1
  {
    $project: {
      mac_id: 1,
      childs: {
        $filter: {
          "input": "$childs",
          "as": "child",
          "cond": {
            "$in": [
              1,
              { $ifNull: ["$$child.config.user_info.mapped_id", []] }
            ]
          }
        }
      }
    }
  }

Playground


第二个选项,这是处理这种情况的正确方法,$lookup 使用管道,

  • letmac_id 传递给管道
  • 检查$expr mac_id 的条件
  • 匹配mapped_id条件
db.gateway.aggregate([
  { $match: { group_id: "0" } },
  {
    $lookup: {
      from: "commands",
      let: { mac_id: "$mac_id" },
      pipeline: [
        {
          $match: {
            $expr: { $eq: ["$mac_id", "$$mac_id"] },
            "config.user_info.mapped_id": 1
          }
        }
      ],
      as: "childs"
    }
  },
  {
    $project: {
      _id: 0,
      mac_id: 1,
      childs: 1
    }
  }
])

Playground

如果您想过滤user_info 数组,那么您可以在$lookup 阶段的$match 阶段之后再添加一个阶段,

{
  $addFields: {
    "config.user_info": {
      $filter: {
        input: "$config.user_info",
        cond: { $eq: ["$$this.mapped_id", 1] }
      }
    }
  }
}

Playground

【讨论】:

  • 谢谢哥们!!我尝试了第一种方法,它奏效了。你知道我的查询出了什么问题吗?
  • 我在答案的顶部添加了解释。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 2018-12-20
  • 2020-08-07
  • 2020-03-07
  • 2016-07-27
  • 2019-09-03
  • 2022-01-05
  • 2021-06-04
相关资源
最近更新 更多