我的对象具有以下结构:
{id: 1234, ownerId: 1, typeId: 3456, date:...}
{id: 1235, ownerId: 1, typeId: 3456, date:...}
{id: 1236, ownerId: 1, typeId: 12, date:...}
我想查询数据库,以便它返回属于给定ownerId
的所有项目,但只返回给定typeId
的第一项。 IE typeId
字段在结果中是唯一的。我还希望能够使用skip
和limit
。
在SQL中,查询类似于:
SELECT * FROM table WHERE ownerId=1 SORT BY date GROUP BY typeId LIMIT 10 OFFSET 300
我目前有以下查询(使用pymongo)但是我在使用$sort
,$limit
和$skip
时出错:
search_dict['ownerId'] = 1
search_dict['$sort'] = {'date': -1}
search_dict['$limit'] = 10
search_dict['$skip'] = 200
collectionName.group(['typeId'], search_dict, {'list': []}, 'function(obj, prev) {prev.list.push(obj)}')
-
我也尝试过汇总路线,但据我所知,分组会触及集合中的所有项目,将它们分组,然后限制并跳过。这将是计算上太昂贵和缓慢的。我需要一个迭代分组算法。
search_dict = {'ownerId':1}
collectionName.aggregate([
{
'$match': search_dict
},
{
'$sort': {'date': -1}
},
{
'$group': {'_id': "$typeId"}
},
{
'$skip': skip
},
{
'$limit': 10
}
])
答案 0 :(得分:0)
您的汇总看起来是正确的。您需要使用$group
在$first
阶段的输出中包含所需的字段。
分组将触摸集合中的所有项目,对它们进行分组,然后限制并跳过。这将是计算上太昂贵和缓慢的。
它不会触及集合中的所有项目。如果匹配+排序已编入索引({ "ownerId" : 1, "date" : -1 }
),则索引将用于匹配+排序,并且该组将仅处理作为匹配结果的文档。
除了未编制索引的情况外,约束几乎不是cpu。它通常是磁盘I / O.
我需要一个迭代分组算法。
“迭代分组”究竟是什么意思?分组是迭代的,因为它迭代前一阶段的结果并检查每个文档属于哪个组!
答案 1 :(得分:-2)
我不确定你是如何理解这个操作应该是计算上昂贵的。对于大多数SQL数据库来说,情况并非如此,而且肯定不适用于MongoDB。您只需要在排序标准上创建一个索引。
以下是如何证明:
打开一个mongo shell并执行此操作。
var bulk = db.speed.initializeOrderedBulkOp()
for ( var i = 1; i <= 100000; i++ ){
bulk.insert({field1:i,field2:i*i,date:new ISODate()});
if((i%100) == 0){print(i)}
}
bulk.execute();
批量执行可能需要几秒钟。接下来,我们创建一个辅助函数:
Array.prototype.avg = function() {
var av = 0;
var cnt = 0;
var len = this.length;
for (var i = 0; i < len; i++) {
var e = +this[i];
if(!e && this[i] !== 0 && this[i] !== '0') e--;
if (this[i] == e) {av += e; cnt++;}
}
return av/cnt;
}
剧团准备就绪,舞台布景:
var times = new Array();
for( var i = 0; i < 10000; i++){
var start = new Date();
db.speed.find().sort({date:-1}).skip(Math.random()*100000).limit(10);
times.push(new Date() - start);
}
print(times.avg() + " msecs");
输出位于 msecs 。这是用于比较的5次运行的输出:
测试服务器在docker镜像内运行,而docker镜像又运行在我的2,13 GHz Intel Core 2 Duo上的VM(boot2docker)中,内存为4GB,运行OSX 10.10.2,很多Safari窗口,iTunes,另外还有Mail,Spotify和Eclipse。不完全是一个生产系统。而且该集合甚至没有日期字段的索引。使用该索引,5次运行的平均值如下所示:
qed,hth。