我的问题:给我一份超过X时间的文件清单.
如果我创建了一个文档:
db.dates.insert({date: new Date()});
现在我只想在"约会"变成30分钟时找到它:
db.dates.find({ $where: "this.date.getTime() + 30 * 60000 <= new Date()"});
这是有效的,但在Mongo文档中明确指出,对于查询的$,存在显着的性能损失.
因此,问题是,还有更好的方法吗?
==========更新1 ==========
我应该补充一点,我希望这个查询功能"动态地"创建一次查询并使用它来获取有限集合上的可用光标...而且我不确定它是否真的可行.
我会测试并重新发布.
==========更新2 ==========
因此,看起来我的"延迟"队列将不得不在代码中处理,无论是使用轮询还是一些"检查,然后睡眠"算法,因为这似乎是mongo的延迟复制正在进行的操作(来自db.cpp):
if ( replSettings.slavedelay && ( unsigned( time( 0 ) ) < nextOpTime.getSecs() + replSettings.slavedelay ) ) {
assert( justOne );
oplogReader.putBack( op );
_sleepAdviceTime = nextOpTime.getSecs() + replSettings.slavedelay + 1;
dblock lk;
if ( n > 0 ) {
syncedTo = last;
save();
}
log() << "repl: applied " << n << " operations" << endl;
log() << "repl: syncedTo: " << syncedTo.toStringLong() << endl;
log() << "waiting until: " << _sleepAdviceTime << " to continue" << endl;
return okResultCode;
}
Run Code Online (Sandbox Code Playgroud)
所以我之前对问题的回答没有通过所有单元测试。除了一个以外,它都通过了:
当可尾游标已附加到集合时,插入最终可用的记录。
测试设置如下:
我能够让它发挥作用的唯一方法是模仿部分延迟的 oplog 逻辑:
if (cursor.hasNext()) {
DBObject obj = cursor.next();
if (config.getQueueDelay() > 0) {
ObjectId objId = (ObjectId) obj.get("_id");
long advisedSleep = (objId.getTime() + config.getQueueDelay() * 60000)
- System.currentTimeMillis();
if (advisedSleep > 0 ) {
LOG.debug(
"object is not yet old enough, sleeping for: "
+ advisedSleep + "ms"
);
Thread.sleep(advisedSleep);
}
}
return obj;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这是一个不错的算法,因为只要相关集合依赖于自动创建的 ObjectId,我们就可以 100% 确定对象的顺序正确,如果我们不能确定这一点,那么我们总是可以将 order by 添加到初始查询中。
另一方面,集合必须有一个 ObjectId(我的代码假设它位于对象的 _id 字段中,但这可以轻松更改为可配置值)。
| 归档时间: |
|
| 查看次数: |
1675 次 |
| 最近记录: |