MongoDB的find和findone调用之间的区别


34

我正在一个项目上,我不确定find游标的工作方式和游标的工作方式之间是否有区别findOne。是findOne的包装find().limit(1)吗?我一直在寻找它,也许有人知道mongodb是否具有特殊的方法。我正在为mongodb使用PHP API,如果有所作为。

Answers:


33

根据我自己的基准,比find().limit(1)几个数量级。findOne()

MongoDB文档中有错误或中的错误findOne()findOne()执行起来更像find().limit(N)N,其中N是查询将返回的文档数。我在试图弄清楚为什么我的简单查询这么慢的时候就想到了这一点!

更新:来自10gen(MongoDB)工程师的回复:

您正在执行的两个查询非常不同。查找查询返回一个游标,这本质上是无操作的情况,因为没有返回实际数据(仅返回游标信息)。如果调用findOne,则实际上是在返回数据并关闭游标。该文档绝对应该更清晰:-)

更新:确实,如果find().limit(1)检索到文档,则数量级速度差异似乎消失了。而且,我无法重现MongoDB JavaScript驱动程序的主要速度差异。我最初使用MongoDB Java驱动程序进行基准测试。


1
很棒的发现。但是,重要的问题是:您的基准测试是否考虑了在find().limit(1)正常编程过程中(无论是实际获取数据还是关闭游标)在任何情况下都会findOne()自动为您执行的额外操作?
Nick Chammas

@尼克:我认为额外的操作已涵盖在内。我正在查找一个随机文档(cookbook.mongodb.org/patterns/random-attribute),使用.next()获取该文档并将其从集合中删除。我没有手动关闭任何游标...
Leftium

@Leftium然后我必须问,执行find.limit(1)然后获得cursur值是否更快?或者进行findone()是否更快?
WojonsTech

2
@WojonsTech:JS中的快速基准测试表明findOne()实际上更快。但是,结果可能因驱动程序/平台而异。例如,我无法重现最初使用Java驱动程序观察到的JS速度差的数量级。
Leftium

2
Leftium,我将编辑您的答案以强调在实际检索文档时(通常是这样),这两个功能实际上是相同的,就像文档中指出的那样。现在,某人可能会在回答的开头阅读粗体行,并得出结论,如果他们要检索一个文档,findOne()则比差find().limit(1),这是不正确的。
Nick Chammas 2012年

5

findOne()的确是语法糖find().limit(1)因为你实际上检索文档(而不是仅仅返回光标find())。

有关更多详细信息,请参见Leftium的答案和更新。


好的,谢谢。我不喜欢在编程中使用synimus函数,而宁愿限制自己一个人,以便我的所有代码都易于跟踪。
WojonsTech

1
实际上,在基准测试中,findOne()比find()。limit(1)快一点。
弗拉基米尔(Vladimir)

@ DairT'arg-如果您有资源或数据来支持此声明,请务必提供详细信息的答案!根据到目前为止的经验,只要在两种情况下都检索文档,它们就应该相同。
Nick Chammas 2012年

3

源代码可能会有所帮助。

它是Java,但我想它也可以提供帮助。

findOne()

DBObject findOne(DBObject o, DBObject fields, DBObject orderBy, ReadPreference readPref,
                 long maxTime, TimeUnit maxTimeUnit) {

    QueryOpBuilder queryOpBuilder = new QueryOpBuilder().addQuery(o).addOrderBy(orderBy)
                                                        .addMaxTimeMS(MILLISECONDS.convert(maxTime, maxTimeUnit));

    if (getDB().getMongo().isMongosConnection()) {
        queryOpBuilder.addReadPreference(readPref);
    }

    Iterator<DBObject> i = find(queryOpBuilder.get(), fields, 0, -1, 0, getOptions(), readPref, getDecoder());

    DBObject obj = (i.hasNext() ? i.next() : null);
    if ( obj != null && ( fields != null && fields.keySet().size() > 0 ) ){
        obj.markAsPartialObject();
    }
    return obj;
}

这是 find()

public DBCursor find( DBObject ref ){
    return new DBCursor( this, ref, null, getReadPreference());
}

正如我们可以看到,findOne()调用find()它的自我,得到所有的DBOjecti,然后返回第一个。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.