我正在努力了解mongodb中重叠的投影如何工作。
这是一个简单的例子来说明我的难题(来自浏览器内mongodb控制台的结果)。
首先,我创建并插入了一个简单的文档:
var doc = {
id:"universe",
systems: {
1: {
name:"milky_way",
coords:{x:1, y:1}
}
}
}
db.test.insert(doc);
// doc succesfully inserted
接下来,我尝试一个有点奇怪的预测:
db.test.find({}, {"systems.1.coords":1, "systems.1":1});
//result
"_id" : ObjectId("537fd3541cdcaf1ba735becb"),
"systems" : {
"1" : {
"coords" : {
"y" : 1,
"x" : 1
}
}
}
}
我希望看到“系统1”的全部内容,包括名称字段。但是,似乎通向“ systems.1.coords”的更深层路径覆盖了仅向“ system.1”的更浅层路径?
我决定测试此“更深的路径优先于较浅的路径”理论:
db.test.find({}, {"systems.1.coords.x":1, "systems.1.coords":1});
//result
"_id" : ObjectId("537fd3541cdcaf1ba735becb"),
"systems" : {
"1" : {
"coords" : {
"y" : 1, // how'd this get here, but for the shallower projection?
"x" : 1
}
}
}
}
在这里,我的较深投影并没有覆盖较浅的投影。
是什么赋予了?mongodb如何处理重叠的投影?我找不到逻辑。
编辑:
我的困惑源于所谓的“顶级”道路。
这按我预期的那样工作:(.findOne({}, {"systems.1":1, "systems":1})
即,返回了整套系统,尽管我开始时似乎是一个“更窄”的投影)。
但是,这没有按我预期的那样工作:(.findOne({}, {"systems.1.name":1, "systems.1":1})
即,仅返回system.1的名称字段)。
简而言之,深入多于“一个点”将导致覆盖已接受的答案中讨论的覆盖。
您无法使用进行此类投影。find()
因为允许的一般预测是基本领域的选择。您正在谈论的是文档重塑,为此您可以将$project
运算符与该.aggregate()
方法配合使用。
因此,通过您的初始示例:
db.test.aggregate([
{ "$project": {
"coords": "$systems.1.coords",
"systems": 1
}}
])
这将为您提供如下输出:
{
"_id" : ObjectId("537fe2127cb762d14e2a1007"),
"systems" : {
"1" : {
"name" : "milky_way",
"coords" : {
"x" : 1,
"y" : 1
}
}
},
"coords" : {
"x" : 1,
"y" : 1
}
}
请注意,这里也有不同的字段命名,因为没有其他原因,来自该版本的版本.find()
会导致您尝试选择的字段级别的路径重叠(“系统”相同),因此不能投影为两个列出您可以在此处执行的操作方式。
以几乎相同的方式,考虑如下语句:
db.test.aggregate([
{ "$project": {
"systems": {
"1": {
"coords": "$systems.1.coords"
}
},
"systems": 1
}}
])
因此,这并不是在告诉您它是无效的,只是投影中的结果之一覆盖了另一个,因为从本质上讲,它们都被称为“系统”。
基本上,当您尝试使用可用于的投影方法来做类似的事情时,最终会得到这样的结果.find()
。因此,最重要的部分是您需要一个不同的字段名称,这就是聚合框架(尽管此处未进行聚合)允许您执行的操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句