Jac*_*ack 11 mongodb mongodb-query
在我的一个集合中经过几个聚合步骤(管道步骤)后,我最终得到以下结果:
{
"_id" : ObjectId("574e7722bffe901713d383bb"),
"eventname" : "Ball Passed",
"command" : {
"_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
"name" : "Run",
"strike" : 15,
"score" : true,
"duration" : 123
}
}
{
"_id" : ObjectId("57ec6b6f6c61e919b578ff8a"),
"eventname" : "Ball Passed",
"command" : {
"_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
"name" : "Run",
"strike" : 12,
"score" : false,
"duration" : 597
}
}
Run Code Online (Sandbox Code Playgroud)
哪个好!
但是,在聚合的下一步中,我希望得到以下结果:
{
"_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
"name" : "Run",
"strike" : 15,
"duration" : 123
}
{
"_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
"name" : "Run",
"strike" : 12,
"duration" : 597
}
Run Code Online (Sandbox Code Playgroud)
如果您有通知,该command字段应该成为顶级文档,command.score应该跳过.
我怎样才能一步到位?如果只能在一个步骤中完成,那么可以分多步进行?我想我要用$project?
Mar*_*nyi 17
如果子文档中有许多字段,有时会使用新字段进行更新,则投影不是可行的选项.幸运的是,自3.4以来,MongoDB有一个名为$ replaceRoot的新运算符.
您所要做的就是在管道末尾添加一个新阶段.
db.getCollection('sample').aggregate([
{
$replaceRoot: {newRoot: "$command"}
},
{
$project: {score: 0 } //exclude score field
}
])
Run Code Online (Sandbox Code Playgroud)
这将为您提供所需的输出.
请注意,在聚合的情况下(特别是在$ group阶段之后),'command'文档可以是一个数组,并且可以包含多个文档.在这种情况下,您需要首先展开数组才能使用$ replaceRoot.
ale*_*xbt 10
正如您所猜测的那样,$project允许您这样做:
db.col.aggregate([
{
$project :
{
_id: "$command._id",
name: "$command.name",
strike: "$command.strike",
duration: "$command.duration"
}
}
]).pretty()
Run Code Online (Sandbox Code Playgroud)
我插入了您之前的结果,上面的查询返回了这个:
{
"_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
"name" : "Run",
"strike" : 15,
"duration" : 123
}
{
"_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
"name" : "Run",
"strike" : 12,
"duration" : 597
}
Run Code Online (Sandbox Code Playgroud)
因此,管道查询本$product应产生你正在寻找的结果.
如果确切的结构不是您的主要关注点,而是排除少数字段(不必列出要包括的所有字段),那么您可以使用find()而不是aggregate().
aggregate该产品只允许您排除_id.这意味着您需要手动列出要包含的所有字段.
注意:从MongoDB版本3.4开始,可以排除$project阶段中的字段(https://docs.mongodb.com/manual/reference/operator/aggregation/project/#exclude-fields)
find 但是,让您列出要隐藏的字段.
(1)您可以使用$ out将聚合结果重定向到另一个集合:
{ $out : "commands" }
Run Code Online (Sandbox Code Playgroud)
(2)即使结构不完全符合您的要求,您也可以进行find查询并隐藏字段:
db.commands.find({}, {_id:0, "command.score":0, eventname:0}).pretty()
Run Code Online (Sandbox Code Playgroud)
它返回这个,这非常接近你想要的:
{
"command" : {
"_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
"name" : "Run",
"strike" : 15,
"duration" : 123
}
}
Run Code Online (Sandbox Code Playgroud)