【问题标题】:Node.js MongoDB Bulk Operation UpdateOne with arrayFiltersNode.js MongoDB 批量操作 UpdateOne 与 arrayFilters
【发布时间】:2020-11-24 20:30:53
【问题描述】:

在批量操作中使用 arrayFilters 执行 NodeJS/MongoDB updateOne 的正确语法是什么?

MongoDB 版本:4.2.5
NodeJS 版本:12.x
npm mongodb 版本:3.6.0

给定以下简化的集合。我需要更新 lineItems 数组中的一个元素。

{
  _id: ObjectId("5d50689fd304e3189aae99ba"),
  "lineItems" : [
    { "importId" : "abc123" },
    { "importId" : "def456" }
  ]
}

以下批量更新适用于 MongoDB shell:

var bulk = db.myCollection.initializeOrderedBulkOp();
bulk
  .find({"_id": ObjectId(myId)})
  .arrayFilters( [ { "elem.importId": "abc123" } ] )
  .updateOne( { $set: { "lineItems.$[elem].meta": { "test": 1 } } } );
bulk.execute();

以下在 NodeJS 中有效(但不是批量操作):

db.collection('myCollection').updateOne(
  { _id: ObjectID(myId) },
  { $set: { 'lineItems.$[elem].meta': { test: 1 } } },
  { arrayFilters: [{ 'elem.importId': lineItem.importId }] }
);

这张票意味着 NodeJS MongoDB 驱动程序支持批量操作的 arrayFilters:
https://jira.mongodb.org/browse/NODE-1911

但是,我尝试了许多不同的变体。但是例如,此代码返回错误“arrayFilters is not a function”。

const bulkOp = db.collection('myCollection').initializeOrderedBulkOp()
bulkOp
  .find({ _id: ObjectId(myId) })
  .arrayFilters([{ 'elem.importId': lineItem.importId }])
  .updateOne({ $set: { 'lineItems.$[elem].meta': { test: 1 } } });

以上基于MongoDB文档中的示例:

bulk
  .find({}).
  arrayFilters( [ { "elem.grade": { $gt: 85 } } ] ).
  updateOne( { $set: { "grades.$[elem].mean" : 70 } } );

https://docs.mongodb.com/v4.2/reference/method/Bulk.find.arrayFilters/#Bulk.find.arrayFilters

【问题讨论】:

  • 你是在shell中执行吗?如果是,那么 shell 的版本是什么?如果没有,那么你可以尝试在 shell 中执行。
  • 我认为您指的是 MongoDB shell。好问题。是的 - 我在问题中添加了一个在 MongoDB shell 中运行时有效的批量更新查询。
  • 还有一个,你正在使用这个npm,这是documentation,这个npm使用mongodb驱动api,对吗?如果是,那么您可以检查他们在文档中解释了 arrayFilters 函数吗?因为我没找到。
  • 您到 npm 和文档的链接都是正确的。我在文档中也找不到任何提及 arrayFilters 的内容。但是,arrayFilters 确实出现在 npm 包源代码中。我在“使用数组过滤器进行批量操作的能力”问题中链接到的 jira 票证具有分辨率 = 固定并暗示它受支持(但也许不是,这就是问题所在)。

标签: node.js mongodb


【解决方案1】:

MongoDB node.js 驱动程序(截至 (3.6.0))似乎尚未正确支持 arrayFilters。

有一个使用“原始”的解决方法的 jira 票: https://jira.mongodb.org/browse/NODE-2101

ticket 中有一个很好的 vanilla node.js 驱动程序示例。但是,如果您尝试使用 Mongoose,这里还有一个基于 MongoDB documentation 的解决方案:

“students3”集合中的 MongoDB 文档:

{
   "_id" : 1,
   "grades" : [
      { "type" : "quiz", "questions" : [ 12, 10, 5 ] },
      { "type" : "quiz", "questions" : [ 10, 11, 6 ] },
      { "type" : "hw", "questions" : [ 5, 4, 3 ] },
      { "type" : "exam", "questions" : [ 25, 10, 23, 0 ] }
   ]
}

Mongoose 代码(MongoDb 4.2.8 使用 Mongoose 5.9.28):

// @ts-ignore (required if "raw" is not part of @types)
const bulk = Students.collection.initializeOrderedBulkOp();
bulk.raw({
    updateOne: {
        updateOne: {
            filter: {_id: mongoose.Types.ObjectId("5ed3243aa83d3a42ccff43e2")},
            update: { $inc: { "grades.$[].questions.$[score]": 2 } },
            arrayFilters: [  { "score": { $gte: 8 } } ]
        }
    }
});

我还发现,如果您尝试基于 ObjectId 进行过滤,则需要在 arrayFilters 中使用 $eq。

【讨论】:

    猜你喜欢
    • 2018-06-21
    • 1970-01-01
    • 2018-05-19
    • 2015-02-09
    • 2021-05-07
    • 2015-10-21
    • 1970-01-01
    • 2013-11-07
    • 2014-12-31
    相关资源
    最近更新 更多