我在mongodb有一个相当大的集合,大约有10万个文档(没有分片)。这是Web应用程序的后端,基本上只允许用户浏览不同的方式来查看此集合中的相同信息。
对于其中一个视图,我尝试使用聚合框架计算字段的出现次数。这意味着聚合整个集合。问题是这个聚合操作(这是一个简单的组,排序和限制管道)需要2秒,这对于Web应用程序来说太慢了。
所以我的问题是;为了缓存此聚合操作的结果,首选解决方案是什么?据我所知,不可能“聚合成”一个新的集合,或类似的东西。目前我找到的唯一解决方案是将整个结果读入变量,然后使用insert将此变量插入到新的集合中 - 但我担心这涉及从数据库发送大量数据=>到我的申请=>回到数据库?
有什么建议吗?
管道示例:
res = items.aggregate([
{ "$group": { "_id": { "item_id": "$item_id", "title": "$title", "category": "$category" }, "count": { "$sum": 1 } } },
{ "$sort": { "count": -1 } },
{ "$limit": 5 }
])
模式基本上就是那3个字段+还有一些真正不相关的字段,即:
doc = {
"item_id": 1000,
"title": "this is the item title",
"category": "this is the item category"
}
我在item_id和所有3个字段上都尝试了索引但没有成功。
答案 0 :(得分:1)
聚合将结果返回到一个文档。结果受限于16M。该文档将返回给应用程序。
如果要“聚合”到集合 - 请使用map-reduce。
map_function = function () {
emit(this.item_id, {"item_id": this.item_id, /* any other info */ "count": 1});
};
reduce_function = function (key, values) {
var result = {"item_id": key, /* any other info should be given from one or any of values array objects */ "count": 0};
values.forEach(function (value) {
result["count"] += value["count"];
});
return result;
};
不确定您是否可以发出结构值 - 请尝试。 BTW发射关键字段很好。