fab*_*ols 5 mongodb conditional-statements
我试图做一个匹配一些嵌套数组条件的 mongodb 查询,但没有成功......
文件:
[
{
"_id":1,
"name":"foo",
"games":[
{
"name":"Game1",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
},
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
},
{
"_id":2,
"name":"bar",
"games":[
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
我想做一个update_many,匹配以下数据:
all documents
AND ( (_id = 1 and games.name = 'Game1' and games.data.data_id = 1 ) OR (_id = 2 and games.name = 'Game2' and games.data.data_id = 1 ) )
set valid = True
Run Code Online (Sandbox Code Playgroud)
因此,对于每个文档,我想更新一个特定的 games.data.data_id 元素。
我试过的
[
{
"_id":1,
"name":"foo",
"games":[
{
"name":"Game1",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
},
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
},
{
"_id":2,
"name":"bar",
"games":[
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
但它返回一个错误:
WriteError: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'i' and 'j'
Run Code Online (Sandbox Code Playgroud)
预期的输出是:
[
{
"_id":1,
"name":"foo",
"games":[
{
"name":"Game1",
"data":[
{ "data_id":1, "date":"YYYMMDD", "valid": True },
{ "data_id":2, "date":"YYYMMDD" }
]
},
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD" },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
},
{
"_id":2,
"name":"bar",
"games":[
{
"name":"Game2",
"data":[
{ "data_id":1, "date":"YYYMMDD", "valid": True },
{ "data_id":2, "date":"YYYMMDD" }
]
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
那么,我做错了什么?这该怎么做?我尝试了其他几种选择,例如组合 $or 和 $and,但是每次我在相同条件下使用多个标识符时,它都会失败
根据使用规则arrayFilters,您不能随意使用条件,例如,中的_id字段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();
Run Code Online (Sandbox Code Playgroud)
更多详情请访问: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"
]
}
}
} }
]
}
}
}
}
}
]
)
Run Code Online (Sandbox Code Playgroud)
3. 聚合管道和更新
此聚合 + 更新适用于 4.2 之前的MongoDB 版本。
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 } } ) )
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1523 次 |
| 最近记录: |