问题描述
是否可以将位置运算符$"与对深层嵌套文档数组的查询结合使用?
Is it possible to use positional operator '$' in combination with a query on a deeply-nested document array?
考虑以下定义用户"的嵌套文档:
Consider the following nested document defining a 'user':
{
username: 'test',
kingdoms: [
{
buildings: [
{
type: 'castle'
},
{
type: 'treasury'
},
...
]
},
...
]
}
我们想为特定用户返回城堡",例如形式:
We'd like to return the 'castles' for a particular user e.g. in a form:
{
kingdoms: [{
buildings: [{
type: 'castle'
}]
}]
}
因为您不能两次使用 $ 运算符 (https://jira.mongodb.org/browse/server-831) 我知道我也不能查询特定的王国,所以我正在尝试为第 n 个王国编写 find 语句.
Because you cannot use the $ operator twice (https://jira.mongodb.org/browse/server-831) I know that I can't also query for a particular kingdom, so I'm trying to write a find statement for the nth kingdom.
这在更新深度嵌套的子文档时似乎很有意义(Mongodb 更新深度嵌套子文档),但我在查找查询方面的成功率较低.
This seems to make sense when updating a deeply-nested sub-document (Mongodb update deeply nested subdocument) but I'm having less success with the find query.
我可以通过查询返回第一个王国的建筑:
I can return the first kingdom's buildings with the query:
db.users.findOne(
{ username: 'test' },
{ kingdoms: {$slice: [0, 1]}, 'kingdom.buildings': 1 }
);
但这会返回所有那个王国的建筑物.
But this returns all the buildings of that kingdom.
按照位置运算符的单级示例,我正在尝试这样的查询:
Following the single-level examples of position operator I'm trying a query like this:
db.users.findOne(
{ username: 'test', 'kingdoms.buildings.type': 'castle' },
{ kingdoms: {$slice: [n, 1]}, 'kingdom.buildings.$': 1 }
);
以如下形式:
db.collection.find( { <array.field>: <value> ...}, { "<array>.$": 1 } )
如文档中所述 http://docs.mongodb.org/manual/reference/operator/projection/positional/#proj.S
as described in the documentation http://docs.mongodb.org/manual/reference/operator/projection/positional/#proj.S
但是这失败并出现错误:
However this fails with the error:
Positional operator does not match the query specifier
大概是因为 Kingdoms.buildings 不被视为数组.我也试过 kingdoms.0.buildings
Presumably because kingdoms.buildings isn't considered an array. I've also tried kingdoms.0.buildings
令人困惑,因为这似乎适用于更新(根据 Mongodb 更新深度嵌套的子文档)
It is confusing because this appears to work for updates (according to Mongodb update deeply nested subdocument)
是我语法错误还是不支持?如果是这样,有没有办法实现类似的目标?
Have I just got the syntax wrong or is this not supported? If so is there a way to achieve something similar?
推荐答案
您收到来自
db.users.findOne(
{ username: 'test', 'kingdoms.buildings.type': 'castle' },
{ kingdoms: {$slice: [n, 1]}, 'kingdom.buildings.$': 1 }
);
因为有拼写错误(kingdom.buildings.$"应该是kingdoms.buildings.$").
但是,这种方式并不能达到您的预期.
$ 始终针对 kingdoms.buildings 路径中的 kingdoms - 第一个数组.
because there is a spelling mistake ("kingdom.buildings.$" should be "kingdoms.buildings.$").
However, this way can not accomplish what you expect.
$ is always aimed at kingdoms in the path of kingdoms.buildings - the first array.
这是应该可以解决问题的方法.
(需要 V2.6+)
This is a way that should be able to solve the problem.
(V2.6+ required)
db.c.aggregate([ {
$match : {
username : 'test',
'kingdoms.buildings.type' : 'castle'
}
}, {
$project : {
_id : 0,
kingdoms : 1
}
}, {
$redact : {
$cond : {
"if" : {
$or : [ {
$gt : [ "$kingdoms", [] ]
}, {
$gt : [ "$buildings", [] ]
}, {
$eq : [ "$type", "castle" ]
} ]
},
"then" : "$$DESCEND",
"else" : "$$PRUNE"
}
}
} ]).pretty();
只保留kingdoms的第一个元素,
db.c.aggregate([ {
$match : {
username : 'test',
'kingdoms.buildings.type' : 'castle'
}
}, {
$redact : {
$cond : {
"if" : {
$or : [ {
$gt : [ "$kingdoms", [] ]
}, {
$gt : [ "$buildings", [] ]
}, {
$eq : [ "$type", "castle" ]
} ]
},
"then" : "$$DESCEND",
"else" : "$$PRUNE"
}
}
}, {
$unwind : "$kingdoms"
}, {
$group : {
_id : "$_id",
kingdom : {
$first : "$kingdoms"
}
}
}, {
$group : {
_id : "$_id",
kingdoms : {
$push : "$kingdom"
}
}
}, {
$project : {
_id : 0,
kingdoms : 1
}
} ]).pretty();
这篇关于在深度嵌套的文档查询中使用 MongoDB 的位置运算符 $的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!