我有一个用于跟踪用户审核数据的mongodb集合。所以基本上这将是数百万份文件。
审核由loginID(用户)及其对项目的活动进行跟踪。例如:userA在日期/时间修改了“第13项”。
案例:我需要根据用户和项目查询过滤器。那很简单。这会返回每个项目数千个文档。我需要按最新日期/时间(降序)列出它们。
问题:如何将新文档插入堆栈顶部? (像上限集合)或者是否可以从堆栈底部找到记录? (相反的顺序)。我不喜欢查找和排序的想法,因为在处理数以千万计的文档时,排序是一个瓶颈。
任何解决方案?
Stack:mongodb,node.js,mongoose。
谢谢!
答案 0 :(得分:3)
堆栈的顶部?
你暗示有一个堆栈,但没有 - 有一棵树,或者更确切地说,是一棵B树。
我不喜欢查找和排序的想法
所以你想排序而不排序?这似乎没有多大意义。堆栈本质上是内存中的数据结构,它们在磁盘上不能很好地工作,因为它们需要巨大的连续块(实际上,大量堆栈在内存中甚至不能很好地工作,并且不断增长的堆栈需要复制整个数据集,几乎没有工作
排序是一个瓶颈
不应该,至少不是紧密存储在一起的数据(数据位置)。排序是一个O(m log n)操作,由于_id
字段已经对时间戳进行编码,因此您已经有一个可以排序的字段。 m
相对较小,所以我在这里看不到问题。你有没有尝试过?使用MongoDB 3.0,索引交叉变得更强大,您甚至可能在复合索引中不需要_id
。
在我的机器上,如果数据在RAM中,从索引过滤的大型集合中的顶级项目需要1ms ("executionTimeMillis" : 1)
。纯粹的网络开销将在同一个联盟中,即使在localhost上也是如此。我使用简单的network creation tool创建了数据,并在mongo控制台中查询了它。
答案 1 :(得分:0)
我遇到了同样的问题。我的解决方案是创建另一个保留前10条记录的附加集合。好的一点是,您可以快速查询。不好的一点是你需要更新额外的收藏。
我发现this启发了我。我用ruby + mongoid实现了我的解决方案。
我的解决方案:
集合定义
class TrainingTopRecord
include Mongoid::Document
field :training_records, :type=>Array
belongs_to :training
index({training_id: 1}, {unique: true, drop_dups: true})
end
维持过程。
if t.training_top_records == nil
training_top_records = TrainingTopRecord.create! training_id: t.id
else
training_top_records = t.training_top_records
end
training_top_records.training_records = [] if training_top_records.training_records == nil
top_10_records = training_top_records.training_records
top_10_records.push({
'id' => r.id,
'return' => r.return
})
top_10_records.sort_by! {|record| -record['return']}
#limit training_records' size to 10
top_10_records.slice! 10, top_10_records.length - 10
training_top_records.save