【问题标题】:MongoDB $lookup in different collections by _id_id 在不同集合中的 MongoDB $lookup
【发布时间】:2021-05-29 18:49:32
【问题描述】:

我有 3 个 mongoDB 集合 我需要用 $lookup 运算符聚合它们,但我什么也没找到/**或者我看起来很糟糕** 第一个是供应商

{
    "_id" : ObjectId("111"), //for example, in db is mongodb ids
    "name" : "supplier 1",   
}

{
    "_id" : ObjectId("222"),
    "name" : "supplier 1",   
}

第二个是客户

{
    "_id" : ObjectId("333"), //for example, in db is mongodb ids
    "name" : "clients 1",   
}

{
    "_id" : ObjectId("444"),
    "name" : "clients 2",   
}

第三个是招式

{
    "_id" : ObjectId("..."), //for example, in db is mongodb ids
    "moveName" : "move 1",
    "agent": ObjectId("111") // this is from suppliers collection   
}

{
    "_id" : ObjectId("..."),
    "moveName" : "move 2", 
    "agent": ObjectId("333") // this one is from CLIENTS collection 
}

所以像输出我需要这样的数据

    {
    "_id" : ObjectId("..."), //for example, in db is mongodb ids
    "moveName" : "move 1",
    **"agent": supplier 1** // this is from suppliers collection   
}

{
    "_id" : ObjectId("..."),
    "moveName" : "move 2", 
    **"agent": clients 1** // this one is from CLIENTS collection 
}

后端是nodejs,我正在使用猫鼬,如果在第一个集合中没有结果,我如何在第二个集合中搜索?

        const moves = await Move.aggregate([
        { $match: query }, // here all wokrs good
        {
            $lookup: {
                from: 'clients',
                localField: 'agent',
                foreignField: '_id',
                as: 'agent'
            }
        },{ $unwind: {path: "$agent" , preserveNullAndEmptyArrays: true} },
        {
            $lookup: {
                from: 'suppliers',
                localField: 'agent',
                foreignField: '_id',
                as: 'agent2'
            }
        },
        {
            $project: {
                operationName: 1,
                agent: {$ifNull: ['$agent.name', '$agent2.name']}
            }
        }
    ])

谢谢!

【问题讨论】:

  • 查看$facet 管道阶段。如果您需要示例和解释,请联系我。

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

正如@hhharsha36 所建议的,我们可以使用$facet 运算符,它允许在一个阶段内运行多个管道。

说明

facet
  suppliers   = $lookup suppliers collection and filter only matched results
  clientes    = $lookup clientes collection and filter only matched results
concatArrays  = We concat suppliers and clients results into a single movies array
unwind        = We flatten movies array [a, b, c] -> a
                                                     b
                                                     c
replaceWith   = We replace the root element [movies:a, movies:b -> a, b]
  mergeObject = allows us to pick the agent name (this way we avoid 1 more stage)

db.moves.aggregate([
  {
    $facet: {
      suppliers: [
        {
          $lookup: {
            from: "suppliers",
            localField: "agent",
            foreignField: "_id",
            as: "agent"
          }
        },
        {
          $match: {
            agent: {
              $not: {
                $size: 0
              }
            }
          }
        }
      ],
      clients: [
        {
          $lookup: {
            from: "clients",
            localField: "agent",
            foreignField: "_id",
            as: "agent"
          }
        },
        {
          $match: {
            agent: {
              $not: {
                $size: 0
              }
            }
          }
        }
      ]
    }
  },
  {
    $project: {
      movies: {
        "$concatArrays": [
          "$clients",
          "$suppliers"
        ]
      }
    }
  },
  {
    $unwind: "$movies"
  },
  {
    $replaceWith: {
      "$mergeObjects": [
        "$movies",
        {
          agent: {
            "$arrayElemAt": [
              "$movies.agent.name",
              0
            ]
          }
        }
      ]
    }
  }
])

MongoPlayground

【讨论】:

    【解决方案2】:

    这个聚合查询给出了想要的结果:

    db.moves.aggregate([
    {   
        $lookup: {
            from: "suppliers",
            localField: "agent",
            foreignField: "_id",
            as: "moves_sup"
        }
    },
    {
        $unwind: { path: "$moves_sup" , preserveNullAndEmptyArrays: true }
    },
    {  
        $lookup: {
            from: "clients",
            localField: "agent",
            foreignField: "_id",
            as: "moves_client"
        }
    },
    {
        $unwind: { path: "$moves_client" , preserveNullAndEmptyArrays: true }
    },
    {
        $addFields: {
            agent: { 
                $cond: [ { $eq: [ { $type: "$moves_sup" }, "object" ] }, 
                         "$moves_sup.name", 
                         { $cond: [ { $eq: [ { $type: "$moves_client" }, "object" ] }, "$moves_client.name", "undefined" ] }
                ] },
           moves_client: "$$REMOVE",
           moves_sup: "$$REMOVE"
        }
    },
    ])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 2019-01-28
      • 2021-09-17
      • 2021-02-22
      • 2020-12-31
      相关资源
      最近更新 更多