我试图获取MongoDB集合中的所有文档
var Order = mongoose.model(' Order',orderSchema());
我原来的想法是使用mongoose db query,但您不能将distinct
与skip and limit
一起用作Distinct is a method that returns an "array", and therefore you cannot modify something that is not a "Cursor":
Order
.distinct('request.headers.custID')
.where('response.status.code').equals(200)
.limit(limit)
.skip(skip)
.exec(function (err, orders) {
callback({
data: orders
});
});
然后我想使用Aggregate
,使用$group
获取不同的customerID记录,$match
返回状态代码为200的所有唯一customerID记录,$project
包括我想要的字段:
Order.aggregate(
[
{
"$project" :
{
'request.headers.custID' : 1,
//other fields to include
}
},
{
"$match" :
{
"response.status.code" : 200
}
},
{
"$group": {
"_id": "$request.headers.custID"
}
},
{
"$skip": skip
},
{
"$limit": limit
}
],
function (err, order) {}
);
这会返回一个空数组。如果我删除project
,则只返回$request.headers.custID
字段,而实际上我需要更多字段。
有什么想法吗?
答案 0 :(得分:3)
关于聚合管道,您需要了解的事情通常是"管道"表示每个阶段仅按执行顺序接收前一阶段发出的输入。这里想到的最好的模拟是" unix pipe" $(".pov_icon_small").on('click',function(){
$(this).parent().siblings().children('div').each(function(value){
if($(this).hasClass('icon'))
$(this).addClass('pov_icon_small').removeClass('pov_icon_large');
else if($(this).hasClass('title'))
$(this).addClass('pov_title_small').removeClass('pov_title_large');
});
$(this).addClass('pov_icon_large').removeClass('pov_icon_small');
$(this).siblings('.title').addClass('pov_title_large').removeClass('pov_title_small');
});
,其中一个命令的输出为"管道输出"对方:
|
因此聚合管道的工作方式与此类似,其中要考虑的另一个主要问题是$project
和$group
阶段仅在发出您要求的字段时运行,而不是其他字段。与SQL等声明性方法相比,这需要一点点习惯,但通过一些实践,它就变成了第二天性。
其他需要考虑的事项是像$match
这样的阶段比在字段选择中放置在管道的开头更重要。这样做的主要原因是可能的索引选择和使用,这极大地加快了速度。此外,ps aux | grep mongo | tee out.txt
后跟$project
的字段选择有点多余,因为无论如何都基本上都是选择字段,并且通常最适合组合。
因此,最优秀的是:
$group
此处要记住的关于Order.aggregate(
[
{ "$match" : {
"response.status.code" : 200
}},
{ "$group": {
"_id": "$request.headers.custID", // the grouping key
"otherField": { "$first": "$otherField" },
// and so on for each field to select
}},
{ "$skip": skip },
{ "$limit": limit }
],
function (err, order) {}
);
的主要内容是除了$group
之外的所有其他字段(这是分组键)需要使用accumulator来选择,因为有_id
实际上,分组键的值总是多次出现。
在这种情况下,我们使用$first
作为累加器,它将首先从分组边界出现。通常这是在$sort
之后使用,但不一定是这样,只要你理解所选内容的行为。
$max
之类的其他累加器只是从分组键内的值中取出字段的最大值,因此独立于"当前记录/文档"与$first
或$last
不同。所以这一切都取决于你的需求。
当然,您可以使用$$ROOT
变量在MongoDB 2.6之后缩小现代MongoDB版本中的选择:
Order.aggregate(
[
{ "$match" : {
"response.status.code" : 200
}},
{ "$group": {
"_id": "$request.headers.custID", // the grouping key
"document": { "$first": "$$ROOT" }
}},
{ "$skip": skip },
{ "$limit": limit }
],
function (err, order) {}
);
这将获取文档中所有字段的副本并将它们放在命名键下(在这种情况下为"文档")。这是一种较短的标记方式,但当然结果文档具有不同的结构,现在所有文档都在一个键下作为子字段。
但只要您了解管道的基本原则"并且不要在之前的阶段排除您想要在以后阶段使用的数据,那么您通常应该没问题。