MongoDB在具有附加字段的对象数组上聚合$lookup

Posted

技术标签:

【中文标题】MongoDB在具有附加字段的对象数组上聚合$lookup【英文标题】:MongoDB Aggregate $lookup on array of object with additional field 【发布时间】:2020-08-14 06:48:40 【问题描述】:

我有两个不同的集合(下面的示例)methods & items。至于现在,我正在使用 3.6 之前的香草聚合查询 $lookup

MongoPlayground Example

  
    $lookup: 
      from: "items",
      localField: "reagents._id",
      foreignField: "_id",
      as: "reagent_items"
    
  

问题是,如果我使用它,我会在原始集合的$lookup 阶段错过quantity 字段(来自methods.reagents 嵌入)。现在,我在lookup 之后立即返回quantity,但据我所知,Mongo 从 3.6 开始为lookup 查询引入了新语法,所以问题是:

它能否解决我收到以下结果的问题:

  
    "_id": 1,
    "name": "Test",
    "reagent_items": [ // <= the exact schema of what I need after lookup
      
        "_id": 1,
        "name": "ItemOne",
        "other": "field",
        "quantity": 2 //quantity field from original array of objects after lookup
      ,
      
        "_id": 2,
        "name": "ItemTwo",
        "other": "field",
        "quantity": 4 //quantity field from original array of objects after lookup
      
    ],
    "reagents": [ //original reagents field here just for example, we could remove it
      
        "_id": 1,
        "quantity": 2
      ,
      
        "_id": 2,
        "quantity": 4
      
    ]
  

方法

    
      "_id": 1,
      "name": "Test",
      "reagents": [
        
          _id: 1,
          quantity: 2
        ,
        
          _id: 2,
          quantity: 4
        
      ]
    

项目

    
      "_id": 1,
      "name": "ItemOne",
      "other": "field"
    ,
    
      "_id": 2,
      "name": "ItemTwo",
      "other": "field"
    

【问题讨论】:

【参考方案1】:

使用$map 和$arrayElemAt 为每个reagent_items 查找对应的reagent 并应用$mergeObjects 以获取一个对象:

db.methods.aggregate([
    
        $lookup: 
            from: "items",
            localField: "reagents._id",
            foreignField: "_id",
            as: "reagent_items"
        
    ,
    
        $project: 
            _id:1,
            name: 1,
            reagents: 1,
            reagent_items: 
                $map: 
                    input: "$reagent_items",
                    as: "ri",
                    in: 
                        $mergeObjects: [
                            "$$ri",
                            
                                $arrayElemAt: [  $filter:  input: "$reagents", cond:  $eq: [ "$$this._id", "$$ri._id" ]   , 0 ]
                            
                        ]
                    
                
            
        
    
])

Mongo Playground

【讨论】:

好吧,我几乎遇到了一个相关查询的问题:如果我在集合中的 _id 字段上有索引应该是 lookuped 并且 reagents 数组有 item_id 反转顺序,例如不是[1,2,3] but [3,2,1], well quantity`字段可能会在$map阶段之后丢失正确的item id。 @AlexZeDim 不确定我是否理解您的担忧,有一个 $eq: [ "$$this._id", "$$ri._id" ] 条件,因此订单不会影响匹配 是的,我一开始没见过,至于现在,我正在重新检查这个东西。至于我的问题,很难用评论中的 500 个符号来描述,但由于模式模式错误,我毁了我的第一个数据库。 你能回答这个问题吗? ***.com/questions/64661069/…@mickl

以上是关于MongoDB在具有附加字段的对象数组上聚合$lookup的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB聚合:计算数组元素或距离之间的差异

mongoDB对嵌套对象数组的聚合查找

MongoDB 聚合 $lookup 到具有管道语法和 _id 作为字符串的父数组字段

具有嵌套对象数组的 MongoDB 聚合

数组中字段的最小值和数组mongodb聚合查询中的第一个对象

MongoDB 聚合两个集合,返回附加字段作为计数