作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图做一个匹配一些嵌套数组条件的 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" }
]
}
]
}
]
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
query = {}
update = {"$set": {"games.$[i].data.$[j].valid": True}}
array_filters = [{'$or': [{'_id': 1, 'i.name': 'Game1', 'j.data_id': 1}, {'_id': 2, 'i.name': 'Game2', 'j.data_id': 1}]}]
WriteError: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'i' and 'j'
[
{
"_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" }
]
}
]
}
]
最佳答案
根据使用规则arrayFilters
,您不能按预期使用条件,例如 _id
字段内 arrayFilters
.看
Specify arrayFilters for Array Update Operations
- In the update document, use the $[] filtered positional operator to define an identifier, which you then reference in the array filter documents. You cannot have an array filter document for an identifier if the identifier is not included in the update document.
- You can include the same identifier multiple times in the update document; however, for each distinct identifier ($[identifier]) in the update document, you must specify exactly one corresponding array filter document. That is, you cannot specify multiple array filter documents for the same identifier.
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();
db.collection.updateMany()
方法可以接受聚合管道
[ <stage1>, <stage2>, ... ]
指定要执行的修改。详情请见:
Update with Aggregation Pipeline
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"
]
}
}
} }
]
}
}
}
}
}
]
)
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 } } ) )
关于mongodb - 具有多个标识符和混合条件(AND/OR)的 arrayFilters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60887573/
我是一名优秀的程序员,十分优秀!