这是我的示例文档:
{
a: 42,
map: {
x: { ... },
y: { ... },
z: { ... }
}
}
我正在寻找一种只返回的方式:
{
a: 42,
map: {
y: { ... }
}
}
我只想在地图中指定字段以保持。像那样......
db.myCollection.find({},
{
"map.y":1
}
)
... 但是它还应该返回字段a
而不明确指定它。
我知道我也可以删除不需要的地图条目:
db.myCollection.find({},
{
"map.x":0,
"map.z":0
}
)
但是这样,在运行查询之前我需要知道哪些地图键可用。
有没有一个很好的方法来处理这个?也许使用聚合框架?
谢谢:)
答案 0 :(得分:2)
这基本上是在MongoDB以及许多其他数据库系统中投影或字段选择的工作原理。这里的概念基本上是"全部或全部",因为如果你没有指定你想要返回的所有字段,它们就不会被返回,当然默认是返回你所不知道的所有字段。特别说出你想要的东西。
因此,返回a
和map.y
的当前数据的正确格式为:
db.myCollection.find({}, { "a": 1, "map.y": 1 })
当然,你告诉它你不想要的东西:
db.myCollection.find({}, { "map.x": 0, "map.z": 0 })
但你不能"混合"包含和排除,唯一的例外是_id
字段,您不希望在结果中出现这种情况,可能会考虑"覆盖索引"查询,但通常你想要主键:
db.myCollection.find({}, { "_id": 0, "a": 1, "map.y": 1 })
对于聚合框架来说,它与$project
和$group
等运营商一样残缺不全。在这两种情况下,您都需要准确指定要返回的内容($ project也遵循一般投影规则),或者结果中不存在这些字段。
事实上,一个常见的错误使我的员工正在“删除”#34;具有其中一个阶段的字段,然后尝试引用稍后删除的字段。它是一个"管道",就像Unix管道|
一样,流向下一阶段的唯一内容就是你指定的内容:
唯一的"真实"如果只是匹配字段而不指定其他字段,则可以通过更改结构来实现" map"作为一个数组,然后使用MongoDB 2.6及更高版本的$redact
管道阶段。虽然有点做作:
db.test.insert({
"a": 42,
"map": [
{ "type": "x", "content": {} },
{ "type": "y", "content": {} },
{ "type": "z", "content": {} }
]
})
对数据结构的聚合操作如下:
db.test.aggregate([
{ "$redact": {
"$cond": [
{ "$eq": [
{ "$ifNull": [ "$type", "y" ] },
"y"
]},
"$$DESCEND",
"$$PRUNE"
]
}}
])
所以我们只要求将元素与" type"匹配。等于" y",但是你通常需要小心,因为$ redact是递归处理的,这就是为什么$ifNull
运算符在测试字段不存在的级别上人为地创建匹配的原因。
但一般来说,投射是全有或全无的。指定要返回的字段,或者它们不在那里。