Node.js MongoDB Bulk Operation UpdateOne с arrayFilters - PullRequest
3 голосов
/ 04 августа 2020

Какой правильный синтаксис для выполнения NodeJS / MongoDB updateOne с arrayFilters в массовой операции?

Версия MongoDB: 4.2.5 NodeJS версия: 12.x npm версия mongodb: 3.6.0

Учитывая следующую упрощенную коллекцию. Мне нужно обновить элемент в массиве lineItems.

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

Следующее массовое обновление работает в оболочке MongoDB:

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 не является функцией».

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

1 Ответ

1 голос
/ 09 августа 2020

Похоже, что arrayFilters еще не поддерживается должным образом драйвером MongoDB node.js (начиная с (3.6.0).

Существует билет jira с обходным путем использования "raw": https://jira.mongodb.org/browse/NODE-2101

В заявке есть хороший пример драйвера vanilla node.js. Однако, если вы пытаетесь использовать Mon goose, вот еще одно решение, основанное на документации MongoDB. :

Документ MongoDB из коллекции "student3":

{
   "_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 ] }
   ]
}

Пн goose Код (MongoDb 4.2.8 с использованием Пн goose 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 } } ]
        }
    }
});

Также я обнаружил, что вам нужно использовать $ eq в arrayFilters, если вы пытаетесь фильтровать на основе ObjectId.

...