代码之家  ›  专栏  ›  技术社区  ›  Homam

当数组中的某个项存在于另一个集合中时,如何在两个集合之间进行查找?

  •  1
  • Homam  · 技术社区  · 6 年前

    在查找管道时,我希望从父文档中的数组中获取链接的记录。

    // Orders
    [{ 
        "_id" : ObjectId("5b5b91a25c68de2538620689"), 
        "Name" : "Test", 
        "Products" : [
            ObjectId("5b5b919a5c68de2538620688"), 
            ObjectId("5b5b925a5c68de2538621a15")
        ]
    }]
    
    // Products
    [
    {
       "_id": ObjectId("5b5b919a5c68de2538620688"),
       "ProductName": "P1"
    },
    {
       "_id": ObjectId("5b5b925a5c68de2538621a15"),
       "ProductName": "P2"
    }
    ,
    {
       "_id": ObjectId("5b5b925a5c68de2538621a55"),
       "ProductName": "P3"
    }
    ]
    

    如何在订单和产品之间进行查找 Products 字段是 数组 !

    我试过这个问题

    db.getCollection("Orders").
        aggregate(
        [
        {
         $lookup:
             {
               from: "Products",
               let: { localId: "$_id" , prods: "$Products" },
               pipeline: [
                  {
                    "$match": 
                    {
                        "_id" : { $in: "$$prods"  }
                    }
                  }, 
    
                  { 
                    $project: 
                    { 
                      "_id": "$_id", 
                      "name": "$prods" ,
                    }
                   }
               ],
               as: "linkedData"
             }
    
        },
        {
            "$skip": 0
        },
        {
            "$limit": 1
        },
        ]
    )
    

    这不起作用,因为 $in 需要一个数组,即使 $$prods 是一个数组,它不接受它。

    我的整个方法正确吗?如何使这个魔法加入?

    3 回复  |  直到 5 年前
        1
  •  2
  •   Ashh    5 年前

    你朝着正确的方向走,你唯一错过的就是 expr 具有 in 与文档相同字段匹配的聚合运算符

    db.getCollection("Orders").aggregate([
      { "$lookup": {
        "from": "Products",
        "let": { "localId": "$_id" , "prods": "$Products" },
        "pipeline": [
          { "$match": { "$expr": { "$in": [ "$_id", "$$prods" ] } } },
          { "$project": { "_id": 1, "name": "$ProductName" } }
        ],
        "as": "linkedData"
      }},
      { "$skip": 0 },
      { "$limit": 1 }
    ])
    

    查看文档 here

        2
  •  1
  •   mickl    6 年前

    你只需要定期 $lookup 文件规定:

    如果您的localfield是一个数组,那么您可能需要向管道添加一个$unwind阶段。否则,localfield和foreignfield之间的相等条件是foreignfield:$in:[localfield.elem1,localfield.elem2,…}。

    因此,对于以下聚合:

    db.Orders.aggregate([
        {
            $lookup: {
                from :"Products",
                localField: "Products",
                foreignField: "_id",
                as: "Products"
            }
        }
    ])
    

    您将获得以下示例数据的结果:

    {
            "_id" : ObjectId("5b5b91a25c68de2538620689"),
            "Name" : "Test",
            "Products" : [
                    {
                            "_id" : ObjectId("5b5b919a5c68de2538620688"),
                            "ProductName" : "P1"
                    },
                    {
                            "_id" : ObjectId("5b5b925a5c68de2538621a15"),
                            "ProductName" : "P2"
                    }
            ]
    }
    
        3
  •  0
  •   Vipul Pandey    6 年前

    在查找之前是否尝试释放。使用“展开”可阻止数组并进行查找。