mch*_*ffe 5 mongodb nosql mongodb-query aggregation-framework
嗨,我是Mongo的新手,我需要收藏,其中一个收藏品我想添加对另一个的引用,并在返回时填充它.
这是一个我想要实现的json示例:
{
"title": "Some Title",
"uid": "some-title",
"created_at": "1412159926",
"updated_at": "1412159926",
"id": "1",
"metadata": {
"date": "2016-10-17",
"description": "a description"
},
"tags": [
{
"name": "Tag 1",
"uid": "tag-1"
},
{
"name": "Tag 2",
"uid": "tag-2"
},
{
"name": "Tag 3",
"uid": "tag-3"
}
]
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的mongo查询,但是它将项目的原始主体嵌套在_id
对象中.
db.tracks.aggregate([{
$unwind: "$tags"
}, {
$lookup: {
from: "tags",
localField: "tags",
foreignField: "_id",
as: "tags"
}
}, {
$unwind: "$tags"
}, {
$group: {
"_id": {
"title": "$title",
"uid": "$uid",
"metadata": "$metadata"
},
"tags": {
"$push": "$tags"
}
}
}])
Run Code Online (Sandbox Code Playgroud)
结果如下:
{
"_id" : {
"title" : "Some Title",
"uid" : "some-title",
"metadata" : {
"date" : "2016-10-17",
"description" : "a description"
}
},
"tags" : [
{
"_id" : ObjectId("580499d06fe29ce7093fb53a"),
"name" : "Tag 1",
"uid" : "tag-1"
},
{
"_id" : ObjectId("580499d06fe29ce7093fb53b"),
"name" : "Tag 2",
"uid" : "tag-2"
}
]
}
Run Code Online (Sandbox Code Playgroud)
有没有办法实现所需的输出?还有一种方法可以不必在$group
我希望返回的所有字段中定义,我想返回原始的Object但是在tags
数组中引用了文档.
非常感谢.
chr*_*dam 17
由于您最初在tags
数组字段上转移了原始文档,这意味着文档将被非规范化,因此$group
管道应使用该_id
字段作为其_id
键,并使用$first
或$last
运算符访问其他字段.
组管道运算符类似于SQL的GROUP BY
子句.在SQL中,GROUP BY
除非使用任何聚合函数,否则不能使用.同样,我们也必须在MongoDB中使用聚合函数,所以不幸的是,没有其他方法可以不必在$group
管道中定义您希望在每个字段上使用$first
or $last
运算符返回的所有字段:
db.tracks.aggregate([
{ "$unwind": "$tags" },
{
"$lookup": {
"from": "tags",
"localField": "tags",
"foreignField": "_id",
"as": "resultingArray"
}
},
{ "$unwind": "$resultingArray" },
{
"$group": {
"_id": "$_id",
"title": { "$first": "$title" },
"uid": { "$first": "$uid" },
"created_at": { "$first": "$created_at" },
"updated_at": { "$first": "$updated_at" },
"id": { "$first": "$id" },
"metadata": { "$first": "$metadata" },
"tags": { "$push": "$resultingArray" }
}
}
])
Run Code Online (Sandbox Code Playgroud)
每当我想调试一个产生意外结果的管道时,我总是使用的一个技巧就是只用第一个管道运算符来运行聚合.如果这给出了预期结果,请添加下一个.
在上面的答案中,你首先尝试聚合$unwind
; 如果有效,请添加$lookup
.这可以帮助您缩小哪个运营商导致问题.在这种情况下,您可以仅使用前三个步骤运行管道,因为您认为$group
是导致问题的管道,然后从该管道检查生成的文档:
db.tracks.aggregate([
{ "$unwind": "$tags" },
{
"$lookup": {
"from": "tags",
"localField": "tags",
"foreignField": "_id",
"as": "resultingArray"
}
},
{ "$unwind": "$resultingArray" }
])
Run Code Online (Sandbox Code Playgroud)
产生输出
/* 1 */
{
"_id" : ObjectId("5804a6c900ce8cbd028523d9"),
"title" : "Some Title",
"uid" : "some-title",
"created_at" : "1412159926",
"updated_at" : "1412159926",
"id" : "1",
"metadata" : {
"date" : "2016-10-17",
"description" : "a description"
},
"resultingArray" : {
"name" : "Tag 1",
"uid" : "tag-1"
}
}
/* 2 */
{
"_id" : ObjectId("5804a6c900ce8cbd028523d9"),
"title" : "Some Title",
"uid" : "some-title",
"created_at" : "1412159926",
"updated_at" : "1412159926",
"id" : "1",
"metadata" : {
"date" : "2016-10-17",
"description" : "a description"
},
"resultingArray" : {
"name" : "Tag 2",
"uid" : "tag-2"
}
}
/* 3 */
{
"_id" : ObjectId("5804a6c900ce8cbd028523d9"),
"title" : "Some Title",
"uid" : "some-title",
"created_at" : "1412159926",
"updated_at" : "1412159926",
"id" : "1",
"metadata" : {
"date" : "2016-10-17",
"description" : "a description"
},
"resultingArray" : {
"name" : "Tag 3",
"uid" : "tag-3"
}
}
Run Code Online (Sandbox Code Playgroud)
从检查中你会看到,对于每个输入文档,最后一个管道输出3个文档,其中3是计算字段中的数组元素的数量,resultingArray
它们都有一个共同的_id
和除了resultingArray
字段不同的其他字段,因此您可以通过添加管道来获得所需的结果,该管道按_id
字段对文档进行分组,然后使用$first
或$last
运算符获取其他字段,如在给定的解决方案中:
db.tracks.aggregate([
{ "$unwind": "$tags" },
{
"$lookup": {
"from": "tags",
"localField": "tags",
"foreignField": "_id",
"as": "resultingArray"
}
},
{ "$unwind": "$resultingArray" },
{
"$group": {
"_id": "$_id",
"title": { "$first": "$title" },
"uid": { "$first": "$uid" },
"created_at": { "$first": "$created_at" },
"updated_at": { "$first": "$updated_at" },
"id": { "$first": "$id" },
"metadata": { "$first": "$metadata" },
"tags": { "$push": "$resultingArray" }
}
}
])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14128 次 |
最近记录: |