Mongodb 聚合框架用父文档展平子文档数据

Mongodb 聚合框架用父文档展平子文档数据,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我正在构建一个在不同网页之间旋转的仪表板。我想把所有幻灯片,是“测试”甲板的一部分,并要求他们适当。在查询之后,我的结果理想情况下是这样的 [ {“url”:http://10.0.1.187“,”位置“:1,”二次“:10}, {“url”:http://10.0.1.189“,“位置”:2,“二分体”:3} ] 我当前有一个如下所示的数据集 { “_id”:ObjectId(“53a612043c24d08167b26f82”), “url”:”http://10.0.1.189", “甲

我正在构建一个在不同网页之间旋转的仪表板。我想把所有幻灯片,是“测试”甲板的一部分,并要求他们适当。在查询之后,我的结果理想情况下是这样的

[
{“url”:http://10.0.1.187“,”位置“:1,”二次“:10},
{“url”:http://10.0.1.189“,“位置”:2,“二分体”:3}
]
我当前有一个如下所示的数据集

{
“_id”:ObjectId(“53a612043c24d08167b26f82”),
“url”:”http://10.0.1.189",
“甲板”:[
{
“标题”:“测试”,
"立场":二,,
“持续时间”:3
}
]
}
{
“_id”:ObjectId(“53a6103e3c24d08167b26f81”),
“甲板”:[
{
“标题”:“测试”,
"立场":一,,
“持续时间”:2
},
{
“标题”:“其他甲板”,
"立场":一,,
“持续时间”:10
}
],
“url”:”http://10.0.1.187"
}
我尝试的查询如下所示:

db.slides.aggregate([
{
“$match”:{
“甲板.标题”:“测试”
}
},
{
“$sort”:{
“甲板位置”:1
}
},
{
“$project”:{
“_id”:0,
“位置”:“$decks.position”,
“持续时间”:“$decks.duration”,
“url”:1
}
}
]);

但这并没有产生我想要的结果。如何查询我的数据集并以最佳方式获得预期结果?

我一发布就意识到我应该使用
$unwind
。这个查询是实现它的最佳方式,还是可以采用不同的方式

db.slides.aggregate([
    {
        "$unwind": "$decks"
    },
    {
        "$match": {
            "decks.title": "Test"
        }
    },
    {
        "$sort": {
            "decks.position": 1
        }
    },
    {
        "$project": {
            "_id": 0,
            "position": "$decks.position",
            "duration": "$decks.duration",
            "url": 1
        }
    }
]);
正如你的标题所暗示的那样,要真正“扁平化”文档,我们总是会采用这种方法,因为没有其他方法可以做到这一点。但是,如果您能够接受将数组向下过滤到匹配元素的情况,则有一些不同的方法

基本上说,如果在数组中只有一个匹配项,那么最快的方法就是简单地使用
.find()
匹配所需的元素并投影:

db.slides.find(
{“decks.title”:“Test”},
{“decks.$”:1}
).sort({“decks.position”:1}).pretty()
这仍然是一个数组,但只要您只有一个匹配的元素,那么它就可以工作。项目也按预期进行排序,当然“标题”字段不会从匹配的文档中删除,因为这超出了简单投影的可能性

{
“_id”:ObjectId(“53a6103e3c24d08167b26f81”),
“甲板”:[
{
“标题”:“测试”,
"立场":一,,
“持续时间”:2
}
]
}
{
“_id”:ObjectId(“53a612043c24d08167b26f82”),
“甲板”:[
{
“标题”:“测试”,
"立场":二,,
“持续时间”:3
}
]
}
另一种方法是,只要您有MongoDB 2.6或更高版本可用,就可以使用操作符和其他一些方法“过滤”并“就地”重新调整阵列形状,而无需实际应用:

db.slides.aggregate([
{“$project”:{
“url”:1,
“甲板”:{
“$setDifference”:[
{ 
“$map”:{
“输入”:“$decks”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.title”,“Test”]},
{ 
“位置”:“$$el.position”,
“持续时间”:“$$el.duration”
},
假的
]
}
}
},
[错误]
]
}
}},
{“$sort”:{“decks.position”:1}
])
这样做的好处是,您可以在不进行“展开”的情况下进行更改,这可以减少大型阵列的处理时间,因为您实际上不是为每个阵列成员创建新文档,然后运行单独的阶段进行“筛选”或另一个阶段进行重塑

{
“_id”:ObjectId(“53a6103e3c24d08167b26f81”),
“甲板”:[
{
"立场":一,,
“持续时间”:2
}
],
“url”:”http://10.0.1.187"
}
{
“_id”:ObjectId(“53a612043c24d08167b26f82”),
“url”:”http://10.0.1.189",
“甲板”:[
{
"立场":二,,
“持续时间”:3
}
]
}
您可以再次使用“过滤”数组,或者如果您愿意,您可以通过添加一个不需要过滤的附加数组来再次“展平”该数组,因为结果已经只包含匹配的项

但是一般来说,如果你能接受它,那么就使用
.find()
,因为这是最快的方法。否则,您所做的对于小数据来说是合适的,或者还有另一种选择需要考虑