web-dev-qa-db-ja.com

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

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

35
WojonsTech

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

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

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

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

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

34
Leftium

findOne()は確かに 構文糖 for find().limit(1)は、実際にドキュメントを取得していることを前提としていますfind()でカーソルを返すだけではありません)。

詳細は Leftium's answer と更新を参照してください。

6
Nick Chammas

ソースコードは大いに役立ちます。

それは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を取得して、最初のものを返します。

3
shellbye