【问题标题】:Update subdocument and delete array field in same mongo query在同一个 mongo 查询中更新子文档并删除数组字段
【发布时间】:2020-10-15 19:51:25
【问题描述】:

我正在使用带有 Node (mongoose) 的 Mongo,我想知道是否可以在同一个查询中执行更新和删除。

我的模型如下:

{
 _id: "1",
 types: ["","", ...],
 items: [{
  name: "item_name",
  type: "type_name"
 }]
}

目前在开发数据库中存在的一个真实示例是这个模型:

{
   "_id":"5eff1a68c75aef6db2facdf8",
   "types":[
      "Tier1",
      "Tier2",
      "TierSpecial",
      "TierSuper"
   ],
   "items":[
      {
         "name":"4x4 016 v1",
         "type":"Tier1"
      },
      {
         "name":"Offroad example",
         "type":"Tier1"
      },
      {
         "name":"Simulation super",
         "type":"TierSuper"
      },
      {
         "name":"Simulation Special",
         "type":"TierSpecial"
      }
   ]
}

所以,我想要:更新子文档中值等于预定值的所有“类型”字段(替换字符串值)。然后从数组“类型”中删除。

例如,以实际例子为例,执行查询并删除类型'Tier1'后,结果应该是:

{
   "_id":"5eff1a68c75aef6db2facdf8",
   "types":[
      "Tier2",
      "TierSpecial",
      "TierSuper"
   ],
   "items":[
      {
         "name":"4x4 016 v1",
         "type":"default"
      },
      {
         "name":"Offroad example",
         "type":"default"
      },
      {
         "name":"Simulation super",
         "type":"TierSuper"
      },
      {
         "name":"Simulation Special",
         "type":"TierSpecial"
      }
   ]
}

请注意,types 现在不包含“Tier1”并进入items,其中类型为“Tier1”现在为“默认”

现在我可以完成这项工作,但需要两个查询,而我想在一个查询中完成。

这两个查询是,第一个更新每个等于“Tier1”的type 字段:

db.collection.update({
  _id: "5eff1a68c75aef6db2facdf8",
  
},
{
  $set: {
    "items.$[elem].type": "default",
    
  }
},
{
  arrayFilters: [
    {
      "elem.type": "Tier1"
    }
  ]
})

第二个删除字符串数组中的值:

db.collection.update({
  _id: "5eff1a68c75aef6db2facdf8",
  
},
{
  $pull: {
    types: "Tier1"
  }
})

但我想做这样的事情:

db.collection.aggregate([
  {
    $facet: {
      "query1": [
        {
          // Update query
        }
      ],
      "query2": [
        {
          // Delete query
        }
      ]
    }
  }
])

通过这种方式可以获得关于“query1”和“query2”的信息。

例如:“更新了 3 个子文档,删除了 1 个类型”

我不知道是否可以在一个查询中做到这一点。

谢谢。

【问题讨论】:

  • 您能否提供此模型的示例数据 { _id: "1", types: ["","", ...], items: [{ name: "item_name", type: "type_name" }] }
  • @Mallik 是的,抱歉。我添加了一个真实的例子,所以现在更容易阅读。

标签: mongodb


【解决方案1】:
//working code from Mongodb version 4.2.6 on windows 10
//regarding your first part of query you can combine both updates ($set and $pull) using aggregate a forEach.
> db.typeColl.find();
{ "_id" : 1, "types" : [ "type1" ], "items" : [ { "name" : "John", "type" : "type1" } ] }
{ "_id" : 2, "types" : [ "type2" ], "items" : [ { "name" : "Mary", "type" : "type2" } ] }
> var vtype = "type2";
> db.typeColl.aggregate([
... {$unwind:"$items"},
... {$match:{"items.type": vtype}},
... ]).forEach(function(doc){
...     print("_id: ",doc._id);
...     print("items type:",doc.items.type);
...     //1st update
...     db.typeColl.updateMany(
...     {"_id":doc._id},
...     {$set:{"items.$[].type":"default"}},
...     {upsert:true});
...     //2nd update
...     db.typeColl.updateMany(
...     {"_id":doc._id},
...     {$pull: {types:vtype}}
...    );
... }
... );
_id:  2
items type: type2
>
> db.typeColl.find();
{ "_id" : 1, "types" : [ "type1" ], "items" : [ { "name" : "John", "type" : "type1" } ] }
{ "_id" : 2, "types" : [ ], "items" : [ { "name" : "Mary", "type" : "default" } ] }
> print("MongoDB",db.version());
MongoDB 4.2.6
>

【讨论】:

    猜你喜欢
    • 2015-03-10
    • 2021-07-01
    • 2017-02-19
    • 2020-06-11
    • 2018-11-07
    • 2015-06-22
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多