我尝试编写查询以返回每个类别中的前X个术语 - 例如前5名,前10名等。每个术语都有一个相关的类别,并且基于另一个stackoverflow question的一些帮助,我设法得到了这个:
db.collection.aggregate([
{
$group : {
_id : {
category: "$uri.category",
term: "$uri.term",
},
total: { $sum : 1 }
}
},
{ $sort : { total : -1 } },
{
$group : {
_id : "$_id.category",
terms: {
$push: {
term: "$_id.term",
total: "$total"
}
}
}
}
]);
上述查询确实有效,并返回如下所示的数据:
[
{ category: "movies",
terms: [ { term: "movie 1", total: 5000 }, { term: "movie 2", total: 200 } ... ]
},
{ category: "sports",
terms: [ { term: "football 1", total: 4000 }, { term: "tennis 2", total: 250 } ... ]
},
]
但是,我试图将术语数组限制为固定数字,即5或10 - 这将对应于每个类别的X个搜索次数。我一直在尝试各种选项,例如在$slice
中添加$push
以减少术语数组,但没有成功。
这可以使用聚合框架实现,还是应该考虑另一种方法?
答案 0 :(得分:3)
从Mongodb 2.6开始,不支持使用$slice
或$push
使用.aggregate()
函数/命令限制数组大小的功能。
这是MongoDb问题跟踪器上的feature request。
我要做的是将汇总结果输出到集合。然后更新集合。
use test;
var rInt = function(x) {
return 1 + ~~(Math.random() * x);
};
var rObj = function() {
return {
"timestamp": new Date(),
"category": "movies" + rInt(5),
"term": "my movie" + rInt(20)
}
};
for (var i = 0, l = 100; i < l; i++) {
db.al.insert(rObj());
}
db.al_out.drop();
db.al.aggregate([
{
$group : {
_id : {
category: "$category",
term: "$term",
},
total: { $sum : 1 }
}
},
{ $sort : { total : -1 } },
{
$group : {
_id : "$_id.category",
terms: {
$push: {
term: "$_id.term",
total: "$total"
}
}
}
}
,{ $out : "al_out" } // output the documents to `db.al_out`
]);
// limit the size of terms to 3 elements.
db.al_out.update( {}, {
$push : {
terms : {
$each : [],
$slice : 3
}
}
}, {
multi:true
});
db.al_out.find();
{ "_id" : "movies1", "terms" : [ { "term" : "my movie7", "total" : 3 }, { "term" : "my movie6", "total" : 3 }, { "term" : "my movie17", "total" : 2 } ] }
{ "_id" : "movies2", "terms" : [ { "term" : "my movie3", "total" : 4 }, { "term" : "my movie11", "total" : 2 }, { "term" : "my movie2", "total" : 2 } ] }
{ "_id" : "movies4", "terms" : [ { "term" : "my movie9", "total" : 3 }, { "term" : "my movie1", "total" : 3 }, { "term" : "my movie7", "total" : 2 } ] }
{ "_id" : "movies3", "terms" : [ { "term" : "my movie19", "total" : 5 }, { "term" : "my movie8", "total" : 4 }, { "term" : "my movie14", "total" : 4 } ] }
{ "_id" : "movies5", "terms" : [ { "term" : "my movie7", "total" : 6 }, { "term" : "my movie17", "total" : 4 }, { "term" : "my movie3", "total" : 2 } ] }
答案 1 :(得分:2)
从MongoDb 3.1.6开始,您现在可以在$ project阶段切片:
{
$project: {
terms: {
$slice: ["$terms", 0, 10]
}
}
}
如果您想将$推送的商品数量限制为10。
答案 2 :(得分:1)
我会在$ sort之后和$ group之前添加$ limit阶段:
{ $limit : 5 },
这应该将当前被推入阵列的文档数量限制为5.这也将限制排序中内存中维护的文档总数,这样可以提高整体性能:
当$ sort紧接在管道中的$ limit之前时,$ sort 操作仅在进展时保持前n个结果,其中n 是指定的限制,MongoDB只需要存储n个项目 存储器中。
http://docs.mongodb.org/manual/reference/operator/aggregation/limit/