我从现有数据库中消耗数据。这个数据库存储系统事件。我的服务应该通过计时器检查这个数据库,检查是否创建了一些新事件,然后上传并处理。像简单的队列实现一样。
问题是 - 每次检查数据库时,我怎样才能获得新文档。我无法使用时间戳,因为事件从不同的源传递到数据库,并且没有任何事件顺序。所以我只需要使用插入顺序。
答案 0 :(得分:5)
有几种选择。
第一个,也是最简单的,如果它与您的用例匹配,是使用上限集合。上限集合是一个预定义大小的集合,充当一种环形缓冲区。一旦收集完毕,它就会开始覆盖文档。对于迭代集合,您只需创建一个“tailable”光标,您将需要一些方法来识别“处理的最后一个文档(即使文档中的一个简单的”完成“标志可以工作,但是在插入文档时它必须存在)如果您真的无法以任何方式修改文档,那么您甚至可以在某处保存最后处理的文档并使用课程时间戳(近似起始位置)并在处理更多文档之前查找最后一个文档。
此解决方案唯一真正的问题是,您可以在集合中编写的文档数量受到限制,并且不会随着时间的推移而增长。您可以对文档执行的写操作有限制(它们不能增长),但听起来并不像是在修改文档。
第二个选项,更复杂,是使用oplog。对于独立配置,您仍需要传递-replSet选项以创建和使用oplog。您将不配置oplog。在分片配置中,您需要单独跟踪每个“副本集”。 oplog包含每个插入的文档,更新,删除服务器上的所有集合/文档。每个条目都包含一个时间戳,操作和id(至少)。以下是各自的例子。
插入
{ "ts" : { "t" : 1362958492000, "i" : 1 },
"h" : NumberLong("5915409566571821368"), "v" : 2,
"op" : "i",
"ns" : "test.test",
"o" : { "_id" : "513d189c8544eb2b5e000001" } }
删除
{ ... "op" : "d", ..., "b" : true,
"o" : { "_id" : "513d189c8544eb2b5e000001" } }
更新
{ ... "op" : "u", ...,
"o2" : { "_id" : "513d189c8544eb2b5e000001" },
"o" : { "$set" : { "i" : 1 } } }
时间戳在服务器上生成,并保证单调增加。这使您可以快速找到感兴趣的文件。
此选项最强大,但您需要做一些工作。
我写了一些演示代码,在一个几乎你想要的集合上创建一个“观察者”。您可以在GitHub上找到该代码。具体来看com.allanbank.mongodb.demo.coordination包中的代码。
HTH,Rob
答案 1 :(得分:1)
如果您的_id类型为ObjectId,可以实际使用时间戳:
prefix = Math.floor((new Date( 2013 , 03 , 11 )).getTime()/1000).toString(16)
db.foo.find( { _id : { $gt : new ObjectId( prefix + "0000000000000000" ) } } )
这样,事件来源的位置或时间无关紧要, 只记录文件插入时(高于之前的计时器)
当然,它是无模式的,你总是可以将诸如isNew之类的字段设置为true, 并将其与查询/光标一起设置为false