В соответствии с правилами использования arrayFilters
, вы не можете использовать условия по своему усмотрению, например, поле _id
в arrayFilters
. См. Укажите arrayFilters для операций обновления массива
- В документе обновления используйте позиционный оператор с фильтром $ [], чтобы определить идентификатор, на который вы затем будете ссылаться в массиве. фильтровать документы. У вас не может быть документа фильтра массива для идентификатора, если идентификатор не включен в документ обновления.
- Вы можете включать один и тот же идентификатор несколько раз в документ обновления; однако для каждого отдельного идентификатора ($ [identifier]) в документе обновления необходимо указать ровно один соответствующий документ фильтра массива. То есть вы не можете указать несколько документов фильтра массива для одного и того же идентификатора.
Вот другие способы обновления; но они не могут использовать arrayFilters
так, как вы хотели.
1. Использование Bulk.find.arrayFilters:
var bulk = db.games.initializeUnorderedBulkOp();
bulk.find( { _id: 1 } )
.arrayFilters( [ { "g.name": "Game1" }, { "d.data_id": 1 } ] )
.updateOne( { $set: { "games.$[g].data.$[d].valid": true } } );
bulk.find( { _id: 2 } )
.arrayFilters( [ { "g.name": "Game2" }, { "d.data_id": 1 } ] )
.updateOne( { $set: { "games.$[g].data.$[d].valid": true } } );
bulk.execute();
Подробнее: Bulk.find.arrayFilters
2. Обновление с помощью конвейера агрегации
Начиная с MongoDB 4.2, метод db.collection.updateMany()
может принимать конвейер агрегации [ <stage1>, <stage2>, ... ]
, который указывает модификации, которые необходимо выполнить. Подробности: Обновление с агрегационным конвейером
db.games.updateMany(
{
$or: [ { $and: [ { _id: 1 }, { "games.name": "Game1" }, { "games.data.data_id": 1 } ] },
{ $and: [ { _id: 2 }, { "games.name": "Game2" }, { "games.data.data_id": 1 } ] }
]
},
[
{
$set: {
games: {
$map: {
input: "$games", as: "g",
in: {
$mergeObjects: [
"$$g",
{ data: {
$map: {
input: "$$g.data", as: "d",
in: {
$cond: [
{ $or: [
{ $and: [ { $eq: [ "$_id", 1 ] }, { $eq: [ "$$g.name", "Game1" ] }, { $eq: [ "$$d.data_id", 1 ] } ] },
{ $and: [ { $eq: [ "$_id", 2 ] }, { $eq: [ "$$g.name", "Game2" ] }, { $eq: [ "$$d.data_id", 1 ] } ] }
] },
{ $mergeObjects: [ "$$d", { valid: true } ] },
"$$d"
]
}
}
} }
]
}
}
}
}
}
]
)
3. Конвейер агрегации и обновление
Это агрегация + обновление работает с версиями MongoDB ранее, чем 4.2 .
db.games.aggregate( [
{
$addFields: {
games: {
$map: {
input: "$games", as: "g",
in: {
$mergeObjects: [
"$$g",
{ data: {
$map: {
input: "$$g.data", as: "d",
in: {
$cond: [
{ $or: [
{ $and: [ { $eq: [ "$_id", 1 ] }, { $eq: [ "$$g.name", "Game1" ] }, { $eq: [ "$$d.data_id", 1 ] } ] },
{ $and: [ { $eq: [ "$_id", 2 ] }, { $eq: [ "$$g.name", "Game2" ] }, { $eq: [ "$$d.data_id", 1 ] } ] }
] },
{ $mergeObjects: [ "$$d", { valid: true } ] },
"$$d"
]
}
}
} }
]
}
}
}
}
}
] ).forEach( doc => db.games.updateOne( { _id: doc._id }, { $set: { games: doc.games } } ) )