如何使用其他集合中的值更新MongoDB集合?

boi*_*222 5 mongodb mongodb-query

我有一个名为MongoDB的集合,properties以及一个名为的集合中的另一个新数据集合newProperties.

我想用两个表中saleNumber相同的所有记录的新值更新单个字段(amountOwed). propertiesnewProperties

当我对值进行硬编码时,我已经能够编写单个更新脚本.在使用数组然后使用forEach循环解析它时,我无法使更新脚本正常工作.有人可以解释如何做到这一点?

所以我从一个名为propertiesthis 的集合开始(我只包括相关字段):

{ 
    "_id" : ObjectId("551816b02eecf1238b3baadb"), 
    "saleNumber" : NumberInt(17917), 
    "saleDetails" : {
        "amountOwed" : 266.0, 
    }
}
{ 
    "_id" : ObjectId("551816b02eecf1238b3baadc"), 
    "saleNumber" : NumberInt(851400070), 
    "saleDetails" : {
        "amountOwed" : 270.0, 
    }
}
Run Code Online (Sandbox Code Playgroud)

我导入一个名为newPropertiesthis 的新集合(请注意amountOwed已更改为salesNumber 17917 的记录):

{ 
    "_id" : ObjectId("551816b02eecf1238b3baadb"), 
    "saleNumber" : NumberInt(17917), 
    "saleDetails" : {
        "amountOwed" : 300.0, 
    }
}
Run Code Online (Sandbox Code Playgroud)

我要的是更新properties.saleDetails.amountOwed与价值newProperties.saleDetails.amountOwed的地方saleNumbers匹配.

这是我写的查询:

newActiveProperties.forEach(function(doc) {
     db.properties.update(
     {
        "saleNumber": doc.saleNumber
        , "auction": ObjectId("56fbf3a8d4c6fe5d73af67c9")
     },
    {
      $set: { "saleDetails.amountOwed": doc.saleDetails.amountOwed}
    },
    {
      multi: true
    });
});
Run Code Online (Sandbox Code Playgroud)

当它运行时,没有任何反应.结果选项卡中没有结果(我使用的是Mongo Chef),并且没有任何记录得到更新.

如果我硬编码saleNumber和amountOwed,我可以让它工作:

db.properties.update(
{
    "saleNumber": "17917"
    , "auction": ObjectId("56fbf3a8d4c6fe5d73af67c9")
},
{
  $set: { "saleDetails.amountOwed": 2000}
},
{
  multi: true
});
Run Code Online (Sandbox Code Playgroud)

我猜它与foreach循环中的语法有关,但我不确定它是什么.有人可以解释如何做到这一点?

ray*_*ray 1

使用 MongoDB v4.2+,

您现在可以$merge在聚合管道中使用来对集合执行更新。

db.properties.aggregate([
  {
    "$lookup": {
      "from": "newProperties",
      "localField": "saleNumber",
      "foreignField": "saleNumber",
      "as": "newPropertiesLookup"
    }
  },
  {
    // only matched records are kept
    "$unwind": "$newPropertiesLookup"
  },
  {
    $project: {
      "saleDetails.amountOwed": "$newPropertiesLookup.saleDetails.amountOwed"
    }
  },
  {
    "$merge": {
      "into": "properties",
      "on": "_id",
      "whenMatched": "merge"
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

这是Mongo游乐场供您参考。


在 MongoDB v4.2 之前,

您可以使用聚合管道来执行$lookup. 然后迭代聚合结果,properties逐一更新匹配的文档。

db.properties.aggregate([
  {
    "$lookup": {
      "from": "newProperties",
      "localField": "saleNumber",
      "foreignField": "saleNumber",
      "as": "newPropertiesLookup"
    }
  },
  {
    // only matched records are kept
    "$unwind": "$newPropertiesLookup"
  }
]).forEach(function(result){
  db.properties.update(
    {
      _id : result._id
    },
    {
      $set: { "saleDetails.amountOwed": result.newPropertiesLookup.saleDetails.amountOwed}
    }
  );
})
Run Code Online (Sandbox Code Playgroud)