Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 聚合/项目子文档作为mongo中的顶级文档_Mongodb_Mongodb Query - Fatal编程技术网

Mongodb 聚合/项目子文档作为mongo中的顶级文档

Mongodb 聚合/项目子文档作为mongo中的顶级文档,mongodb,mongodb-query,Mongodb,Mongodb Query,在我的一个集合中执行了几个聚合步骤(管道步骤)之后,我将得到以下结果: { "_id" : ObjectId("574e7722bffe901713d383bb"), "eventname" : "Ball Passed", "command" : { "_id" : ObjectId("57ec6b6f6c61e919b578fe7c"), "name" : "Run", "strike" : 15, "s

在我的一个集合中执行了几个聚合步骤(管道步骤)之后,我将得到以下结果:

{
    "_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
    }
}
{
    "_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
    "name" : "Run",
    "strike" : 15,
    "duration" : 123
}
{
    "_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
    "name" : "Run",
    "strike" : 12,
    "duration" : 597
}
这很好

但是,在聚合的下一步中,我希望得到以下结果:

{
    "_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
    }
}
{
    "_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
    "name" : "Run",
    "strike" : 15,
    "duration" : 123
}
{
    "_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
    "name" : "Run",
    "strike" : 12,
    "duration" : 597
}
如果您已经注意到,
command
字段应该成为顶级文档,并且应该跳过
command.score


我如何一步到位?如果在一个步骤中不可能,那么在多个步骤中?我想我必须使用
$project

正如您所猜测的,
$project
允许您这样做:

db.col.aggregate([
{
    $project : 
    {
        _id: "$command._id",
        name: "$command.name", 
        strike: "$command.strike", 
        duration: "$command.duration"
    }
}
]).pretty()
我插入了您以前的结果,上面的查询返回了以下结果:

{
    "_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
    "name" : "Run",
    "strike" : 15,
    "duration" : 123
}
{
    "_id" : ObjectId("573d688d080cc2cbe8aecbbc"),
    "name" : "Run",
    "strike" : 12,
    "duration" : 597
}
因此,使用此
$product
管道化查询应该会产生您正在寻找的结果

评论后更新 如果您主要关心的不是确切的结构,而是排除几个字段(不必列出要包含的所有字段),那么您可以使用
find()
而不是
aggregate()

aggregate
的产品仅允许您排除\u id。这意味着您需要手动列出要包括的所有字段。
注意:从MongoDB的3.4版开始,可以排除
$project
阶段()

find
但是,您可以列出要隐藏的字段

可供替代的 (1)您可以使用以下方法将聚合结果重定向到另一个集合:

(2)即使结构不完全符合您的要求,您也可以执行
查找
查询和隐藏字段:

db.commands.find({}, {_id:0, "command.score":0, eventname:0}).pretty()
它返回的结果与您要查找的内容非常接近:

{
    "command" : {
        "_id" : ObjectId("57ec6b6f6c61e919b578fe7c"),
        "name" : "Run",
        "strike" : 15,
        "duration" : 123
    }
}

如果子文档中有很多字段,并且偶尔会使用新字段更新,则投影不是一个可行的选项。幸运的是,从3.4开始,MongoDB有了一个名为的新操作符

您所要做的就是在管道的末尾添加一个新阶段

db.getCollection('sample').aggregate([
    {
        $replaceRoot: {newRoot: "$command"}
    },
    {
        $project: {score: 0 } //exclude score field
    }
])
这将为您提供所需的输出


注意,在聚合的情况下(特别是在阶段之后),“命令”文档可以是一个数组,并且可以包含多个文档。在这种情况下,您首先需要数组才能使用

启动
Mongo 4.2
,聚合操作符可用于将一个文档替换为另一个文档(在本例中为子文档),作为
$replaceRoot
的语法糖

// { "eventname": "Ball Passed", "command": { "_id": "57e...", "name": "Run", "strike": 15, "score": true,  "duration": 123 } }
// { "eventname": "Ball Passed", "command": { "_id": "573...", "name": "Run", "strike": 12, "score": false, "duration": 597 } }
db.collection.aggregate([
  { $replaceWith: "$command" }, // replaces the document by the content of "command"
  { $unset: ["score"] }         // drops the "score" field
])
// { "_id" : "57e...", "name" : "Run", "strike" : 15, "duration" : 123 }
// { "_id" : "573...", "name" : "Run", "strike" : 12, "duration" : 597 }

另请注意,
Mongo 4.2
中也引入了聚合运算符,作为
$project
仅用于删除字段时的另一种语法。

我已经简化了文档。实际上,我在
command
子文档中有70多个字段。我是否应该像上面那样对每个字段进行投影?是否有其他方法可以投影所有字段,但只跳过一个字段?我相信聚合只能让您隐藏_id。否则,逻辑只能在“要显示的字段列表”中工作。您还可以使用$out重定向结果,然后使用find(),其工作方式与此相反:它允许您列出要隐藏的字段..我使用建议更新了答案(“注释后更新”部分),因为MongoDB 3.4
$project
可以排除字段: