我是节点(v0.10)堆栈的新手。 我正在努力实现以下目标:
我(希望)在最新的MongoDB中有多语言文章,例如:
_id
...more fields...
text: [
{lang: 'en', title: 'some title', body: 'body', slug: 'slug'},
....
]
每次我以特定语言展示文章时,我都会查询如下:
var query = Model.findOne({'text.slug': slug});
query.exec(function(err, doc){
async.each(doc.text, function(item, callback){
if (item.lang == articleLang) {
//populate the article to display
}
});
res.render('view', {post:articleToDisplay});
});
Slug对每种语言都是独一无二的! 我遇到的问题是mongo将返回包含所有subdocs的整个doc,而不仅仅是我搜索的subdoc。现在我必须选择迭代所有的子目录并在客户端显示相应的子目录,或者在服务器上使用async.each来获取我需要的子目录,并且只发送给那个的视图。我在服务器上使用异步执行此操作。这可以吗?异步也异步迭代,但节点仍然等待整个循环完成,然后呈现视图。在async.each完成之前,我是否遗漏了任何认为用户实际被阻止的内容?我仍然试图围绕这个异步执行。有没有办法可以改进我管理这段代码的方式?这似乎是与subdocs相当标准的程序!
提前感谢您的帮助。
答案 0 :(得分:0)
要实现您的目标,您需要使用aggregation pipeline
。使用简单的findOne()
无济于事,
因为您必须在代码中编辑子文档而不是允许mongodb执行它。 find()
和findOne()
返回整个文档
文档符合搜索条件。
在聚合pipleline中,您可以使用$unwind
和$match
运算符来实现此目的。
$unwind:
从输入文档解构数组字段以输出a 每个元素的文档。每个输出文档都是输入文档 将数组字段的值替换为元素。
首先根据text
值数组展开文档。
$match:
过滤文档以仅传递与文档匹配的文档 指定的条件到下一个管道阶段。
然后使用$match
运算符匹配相应的文档。
db.Model.aggregate([
{$unwind:"$text"},
{$match:{"text.slug":slug,"text.lang":articleLang}}
])
这样做只会返回一个文档,其text
字段只包含一个对象。例如:(注意输出中的text
字段不是数组)
{ "_id" : ... ,.., "text" : { "slug" : "slug", "lang" : "en" ,...} }