我正在尝试从文章集合中生成导航。我有不同语言的文章。我遇到的问题是在lang字段中标有“*”的文章应该出现在每种语言中。所以我必须复制并在每个导航中插入它们。使用聚合框架会有可能吗?
[
{ "$match": { "active":{ "$gte" :0 } }},
{ "$project":{
"_id" :1,
"lang":"$lang",
"topNav": { "name": "$title", "link": "$path" }
}},
{ "$group": {
"_id":{ "lang":'$lang'},
"topNav":{ "$push": "$topNav" }
}},
{ "$out": "navigation" }
]
最终数组
[
{
"_id" :{ "lang":"en" },
"topNav":[
{
"name": "Main Article",
"link": "/"
},
{
"name": "Admin",
"link": "/admin"
}
]
},{
"_id" :{ "lang":"de" },
"topNav":[
{
"name": "Main Article De",
"link": "/"
},
{
"name": "Admin",
"link": "/admin"
}
]
}
]
文章
{
"_id" : ObjectId("1"),
"path" : "/",
"title" : "Main Article",
"content" : "Main Site!",
"lang" : "en",
},{
"_id" : ObjectId("2"),
"path" : "/admin",
"title" : "Admin",
"content" : "Admin Site!",
"lang" : "*",
},{
"_id" : ObjectId("3"),
"path" : "/",
"title" : "Main Article De",
"content" : "Main Site! De",
"lang" : "de",
}
答案 0 :(得分:0)
我不相信这可以通过聚合框架实现,或者至少在没有很大困难和/或架构修改的情况下是不可能的。问题在于,每个文档在通过聚合阶段时都会生成0或1个文档" upserts",其中更新可以在$group
阶段发生,但{{1}除外}运算符,它可以生成文档的副本,除了展开的数组字段有一个特定元素作为其值。
但是,如果可行,您可以尝试将$unwind
更改为语言数组,将所有可能的语言放在每个* doc上的数组中,而不是*:
lang
然后像下面的管道做你想要的:
> db.articles.insert({
"_id" : 0,
"path" : "/",
"title" : "Main Article",
"content" : "Main Site!",
"lang" : ["en"]
})
> db.articles.insert({
"_id" : 1,
"path" : "admin",
"title" : "admin",
"content" : "admin site",
"lang" : ["en", "de"]
}
> db.articles.insert({
"_id" : 2,
"path" : "/",
"title" : "Main Article De",
"content" : "Main Site! De",
"lang" : ["de"]
})
显然,这并不理想,特别是如果你有一套动态的语言需要支持。它确实为您提供了能够使用任意语言标记文章并将其正确分组的好处:D
对于您的用例,我猜测所涉及的对象数量足够小,您可以很好地处理客户端代码中的*案例,所以这一切只是为了好奇/后代。