我有一个集合:
{'_id':'008','name':'ada','update':'1504501629','star':3.6,'desc':'ok', ...}
{'_id':'007','name':'bob','update':'1504501614','star':4.2,'desc':'gb', ...}
{'_id':'005','name':'ada','update':'1504501532','star':3.2,'desc':'ok', ...}
{'_id':'003','name':'bob','update':'1504501431','star':4.5,'desc':'bg', ...}
{'_id':'002','name':'ada','update':'1504501378','star':3.4,'desc':'no', ...}
{'_id':'001','name':'ada','update':'1504501325','star':3.6,'desc':'ok', ...}
{'_id':'000','name':'bob','update':'1504501268','star':4.3,'desc':'gg', ...}
...
如果我想要的结果是,同一'name'的'update'的最大值,意味着'name'的最新文档,得到整个文档:
{'_id':'008','name':'ada','update':'1504501629','star':3.6,'desc':'ok', ...}
{'_id':'007','name':'bob','update':'1504501614','star':4.2,'desc':'gb', ...}
...
如何最有效?
我现在在python中这样做:
result=[]
for name in db.collection.distinct('name'):
result.append(db.collection.find({'name':name}).sort('update',-1)[0])
是否'找'过多次?
=====
我这样做是为了使用'name'抓取数据,获取许多其他密钥,每次插入文档时,我都会设置一个名为'update'的密钥。 当我使用数据库时,我想要特定“名称”的最新文档。所以它看起来不能只使用$ group。 我应该怎么做?重新设计数据库结构或更好的查找方法?
=====
改进了!
我试过创建'name'的索引& '更新',过程从半小时缩短到30秒!
但我仍然欢迎更好的解决方案^ _ ^
答案 0 :(得分:0)
您的用例场景非常适合聚合。正如我在您的问题中看到的那样,您已经知道但无法弄清楚如何使用$group
并获取具有最大更新的整个文档。如果您在$sort
之前$group
提交了文档,则可以使用$first
运算符。因此,无需为每个名称发送查询查询。
db.collection.aggregate(
{ $sort: { "name": 1, "update": -1 } },
{ $group: { _id: "$name", "update": { $first: "$update" }, "doc_id": { $first: "$_id" } } }
)
我没有添加额外的$project
操作进行汇总,您只需将结果中的字段添加到$group
$first
运算符即可。
此外,如果您仔细观察$sort
操作,可以看到它使用您新创建的索引,因此您最好添加它,否则我也会推荐它:)
更新:对于您的评论中的问题:
您应该在$group
中写下所有密钥。但是如果你认为它看起来很糟糕,或者将来会出现新的文件并且不希望每次都重写$group
,我会这样做:
首先在聚合中获取所需文档的所有_id
字段,然后使用find
运算符在一个$in
查询中获取这些文档。
db.collection.find( { "_id": { $in: [<ids returned in aggregation] } } )