MongoDBのfind呼び出しとfindone呼び出しの違い


34

私はプロジェクトに取り組んでいfindますが、カーソルの動作とカーソルの動作に違いがあるかどうかはわかりませんfindOne。findOneは単なるラッパーfind().limit(1)ですか?私はそれを探していましたが、mongodbに特別な方法があるかどうかを誰かが知っているかもしれません。それが違いを生むのであれば、mongodbのPHP APIを使用しています。

回答:


33

私自身のベンチマークに基づいて、find().limit(1)はのよりも桁違いに高速ですfindOne()

MongoDBのドキュメントに誤りがあるか、にバグがありfindOne()ます。Nは、クエリが返すドキュメントの数にfindOne()find().limit(N)ています。私の単純なクエリがなぜそんなに遅いのかを理解しようとして、私はこれを理解しました!

更新: 10gen(MongoDB)エンジニアからの応答:

実行する2つのクエリは非常に異なります。検索クエリはカーソルを返します。これは、実際のデータ(カーソル情報のみ)が返されないため、基本的に操作なしのシナリオです。findOneを呼び出すと、実際にはデータを返し、カーソルを閉じています。ドキュメントは間違いなく明確である必要があります:-)

更新:確かに、find().limit(1)ドキュメントが取得されると、速度の差は桁違いに消えるように見えます。また、MongoDB JavaScriptドライバーとの速度の大きな違いを再現できませんでした。元々、MongoDB Javaドライバーを使用してベンチマークを行いました。


1
素晴らしい発見。しかし、重要な質問:ベンチマークは、とにかく自動的find().limit(1)に行われる通常のプログラミング(実際にデータを取得してカーソルを閉じるなど)の間に行う必要のある追加の操作を考慮findOne()していますか?
ニックチャマス

@Nick:追加の操作がカバーされたと思う。ランダムなドキュメント(cookbook.mongodb.org/patterns/random-attribute)を見つけて、.next()でドキュメントを取得し、コレクションから削除していました。手動でカーソルを閉じませんでした...
レフティウム

@Leftiumその後、find.limit(1)を実行してcursur値を取得する方が速いか、findone()を実行する方が速いかを尋ねる必要があります
WojonsTech

2
@WojonsTech:JSの簡単なベンチマークは、findOne()が実際に高速であることを示しています。ただし、結果はドライバー/プラットフォームによって異なる場合があります。たとえば、Javaドライバーで最初に観察したJSの桁違いの速度差を再現できませんでした。
レフティウム

2
レフティアム、あなたの答えを編集して、実際にドキュメントを取得するとき(通常はそうする)、ドキュメントが述べているように、2つの関数は実際には同一であることを強調します。今、誰かが答えの冒頭の太字の行を読んで、1つのドキュメントを取得したいfindOne()場合find().limit(1)、が間違っていると判断します。
ニックチャマス

5

findOne()(でカーソルを返すだけではなく)実際にドキュメントを取得していることを考えると、はの構文糖衣です。find().limit(1)find()

詳細については、Leftiumの回答と更新を参照してください。


大丈夫、私のプログラミングでsynimus関数を使用するのは好きではありません。すべてのコードを簡単に追跡できるように、自分で1つだけに制限します。
WojonsTech

1
実際、ベンチマークではfindOne()はfind()。limit(1)よりも少し高速です。
ウラジミール

@ DairT'arg-この申し立てをバックアップするソースまたはデータがある場合は、必ず詳細を記載した回答を投稿してください!私がこれまでに収集したものから、両方のケースでドキュメントを取得している限り、それら同一であるべきです。
ニックチャマス

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してから最初の戻ります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.