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

#1 楼

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

MongoDB文档中有错误或findOne()中有错误。 findOne()的执行效果与find().limit(N)相似,其中N是查询将返回的文档数。我在想出为什么我的简单查询如此慢的原因时想出了这一点!

更新:来自10gen(MongoDB)工程师的响应:


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


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

评论


很棒的发现。但是,重要的问题是:在正常编程(例如实际检索数据并关闭游标)的过程中,基准会自动处理findOne()必须执行的find()。limit(1)操作吗?反正为你呢?

–尼克·查玛斯(Nick Chammas)
2011年11月4日在6:07

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

– Leftium
2011年11月4日在6:41

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

– Leftium
2011年11月7日,下午5:24

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

–尼克·查玛斯(Nick Chammas)
2012年4月18日15:57

@bigp这不是有效的性能提示,在实际检索文档时,这两种方法是相同的。

–JohnnyHK
19年1月15日在13:44

#2 楼

findOne()实际上是find().limit(1)的语法糖,因为您实际上正在检索文档(而不是仅使用find()返回游标)。

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

评论


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

– WojonsTech
2011年11月3日17:51

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

–弗拉基米尔
2012年4月25日9:21



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

–尼克·查玛斯(Nick Chammas)
2012年4月25日15:50

#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(),获取了DBOject中的所有i,然后返回第一个。

#4 楼

您必须检查此链接...

http://mongoosejs.com/docs/2.7.x/docs/finding-documents.html


查找-选项返回数组[]
findOne-选项返回文档{}