如何使用另一个集合的值更新MongoDB集合?

6
我有一个名为properties的MongoDB集合,还有一个名为newProperties的新数据集合。
我想要更新properties中的单个字段(amountOwed),使用newProperties中的新值,在两个表中saleNumber相同的所有记录中进行更新。
当我硬编码值时,我能够编写单个更新脚本。但是,当使用数组并使用forEach循环解析它时,我无法使更新脚本正常工作。请问有人可以解释如何做到这一点吗?
所以,我从一个名为properties的集合开始,它看起来像这样(我只包括相关字段):
{ 
    "_id" : ObjectId("551816b02eecf1238b3baadb"), 
    "saleNumber" : NumberInt(17917), 
    "saleDetails" : {
        "amountOwed" : 266.0, 
    }
}
{ 
    "_id" : ObjectId("551816b02eecf1238b3baadc"), 
    "saleNumber" : NumberInt(851400070), 
    "saleDetails" : {
        "amountOwed" : 270.0, 
    }
}

我导入了一个名为newProperties的新集合,它看起来像这样(请注意,amountOwed已经更改为销售编号为17917的记录):

{ 
    "_id" : ObjectId("551816b02eecf1238b3baadb"), 
    "saleNumber" : NumberInt(17917), 
    "saleDetails" : {
        "amountOwed" : 300.0, 
    }
}

我想更新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
    });
});

当它运行时,什么都不会发生。结果选项卡中没有结果(我正在使用Mongo Chef),也没有记录被更新。

如果我直接编写销售编号和应付金额,我可以使其正常工作:

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

我猜这与foreach循环中的语法有关,但我不确定具体是什么。能否有人解释一下如何做到这一点?
1个回答

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"
    }
  }
])

这是您参考的Mongo playground


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}
    }
  );
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接