过滤和更新 mongodb mongoose 中的嵌入式数组

Posted

技术标签:

【中文标题】过滤和更新 mongodb mongoose 中的嵌入式数组【英文标题】:Filter and update embedded Array in mongodb mongoose 【发布时间】:2020-10-01 11:44:31 【问题描述】:

MongoDb 模型如下所示:


    "_id": 
        "$oid": "5ee269c949c9d58970528d1e"
    ,
    "parent": [
        
            "_id": 
                "$oid": "5ee269c949c9d58970528d1d"
            ,
            "uType": "parent",
            "fName": "p1",
            "lName": "p1",
            "num": "123"
        
    ],
    "child": [
        
            "_id": 
                "$oid": "5ee269c949c9d58970528d1c"
            ,
            "uType": "child",
            "fName": "c1",
            "lName": "c1",
            "num": "8963",
            "email": "c1@gmail.com",
            "gender": "male"
        
    ]

我有一个看起来像这样的传入对象 -


    "uType":"child",
    "fName": "c2",
    "lName": "c2",
    "num": "98733",
    "email": "c2@gmail.app",
    "invite": 
        "uType": "parent",
        "fName": "p1",
        "lName": "p1",
        "num": "123"
    

我必须过滤传入的对象,以便得到如下所示的响应——这意味着对于传入的对象,有一个匹配的父对象,但没有匹配的子对象。

尝试使用 $or 并提供了多个条件,但每次最终都会在子数组中获得一条记录。我也尝试使用聚合,但找不到可能的解决方案。谁能告诉我最好的方法是什么?


    "_id": 
        "$oid": "5ee269c949c9d58970528d1e"
    ,
    "parent": [
        
            "isActive": false,
            "_id": 
                "$oid": "5ee269c949c9d58970528d1d"
            ,
            "uType": "parent",
            "fName": "p1",
            "lName": "p1",
            "num": "123"
        
    ],
    "child": [ ]

更新:尝试使用投影,但仍然没有运气 -

Model.aggregate([
            
                $project: 
                    child: 
                        $filter: 
                            input: "$child",
                            as: "ch",
                            cond:  $eq: ["$ch.num", this.num] 
                        
                    
                
            
        ])

【问题讨论】:

uType.invite 总是"parent"uType 总是"child"? @thammada - 是的 【参考方案1】:

实际上,您如此接近解决方案,如果您使用 "$$ch.num" 而不是 "$ch.num" 它应该可以工作。

const match = 
    "uType":"child",
    "fName": "c2",
    "lName": "c2",
    "num": "98733",
    "email": "c2@gmail.app",
    "invite": 
        "uType": "parent",
        "fName": "p1",
        "lName": "p1",
        "num": "123"
    

Model.aggregate([
  
    $match: 
      $or: [
        
          "parent.num": match.invite.num
        ,
        
          "child.num": match.num
        
      ]
    
  ,
  
    $project: 
      parent: 
        $filter: 
          input: "$parent",
          as: "p",
          cond: 
            $eq: [
              "$$p.num",
              match.invite.num
            ]
          
        
      ,
      child: 
        $filter: 
          input: "$child",
          as: "ch",
          cond: 
            $eq: [
              "$$ch.num",
              match.num
            ]
          
        
      
    
  
])

但是你可以在没有聚合的情况下做类似的事情,但是当没有匹配时你不会得到一个空数组,你不会得到键。

Model.find(
  $or: [
    
      "parent.num": match.invite.num
    ,
    
      "child.num": match.num
    
  ]
,

  parent: 
    $elemMatch: 
      num: match.invite.num
    ,
  ,
  child: 
    $elemMatch: 
      num: match.num
    
  
)

【讨论】:

第二种方法实际上效果很好,除了我丢失了其他键值对。仅在响应中获取父数组。如何保留其他密钥? 如果您使用.find,则无法做到这一点。我认为您可以在获得查询结果后轻松将其添加到应用程序层中,因为您会确定是否缺少parentchild,它应该是一个空数组。 或者有没有parentchild不存在的实际情况?

以上是关于过滤和更新 mongodb mongoose 中的嵌入式数组的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB(Mongoose)更新数组数组中的元素

如何使用 Mongoose 只更新 MongoDB 中的一个属性?

如何使用 mongoose 更新 mongodb 中的对象?

Mongoose 不更新 mongodb 中的数组

如何使用 MongoDB/Mongoose 中的先前值更新字段 [重复]

MongoDB使用基于子文档的Mongoose过滤器