MongoDB $其中查询和tailable游标 - WAS:日期数学最佳实践

Jus*_*fey 5 mongodb

我的问题:给我一份超过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)

Jus*_*fey 0

所以我之前对问题的回答没有通过所有单元测试。除了一个以外,它都通过了:

当可尾游标已附加到集合时,插入最终可用的记录。

测试设置如下:

  1. 在单独的线程中将可尾游标附加到集合。
  2. 在主线程中将一个文档插入到集合中,该文档应该在 X 时间内可用。
  3. 让主线程休眠 X 时间。
  4. 查看具有tailable游标的线程是否有该文档。

我能够让它发挥作用的唯一方法是模仿部分延迟的 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 字段中,但这可以轻松更改为可配置值)。