it-swarm.com.de

Unterschied zwischen MongoDBs Find- und Findone-Aufrufen

Ich arbeite an einem Projekt und bin mir nicht sicher, ob es einen Unterschied zwischen der Funktionsweise des Cursors find und der Funktionsweise des Cursors findOne gibt. Ist findOne nur ein Wrapper für find().limit(1)? Ich habe mich danach umgesehen und vielleicht weiß jemand, ob Mongodb eine spezielle Methode dafür hat oder nicht. Ich arbeite mit der PHP API für Mongodb, wenn das einen Unterschied macht.

35
WojonsTech

Basierend auf meinen eigenen Benchmarks ist find().limit(1) um Größenordnungen schneller als findOne().

Es liegt entweder ein Fehler in der MongoDB-Dokumentation oder ein Fehler in findOne() vor. findOne() funktioniert eher wie find().limit(N) wobei N die Anzahl der Dokumente ist, die die Abfrage zurückgeben würde. Ich habe das herausgefunden, als ich versucht habe herauszufinden, warum meine einfachen Abfragen so langsam waren!

pdate : Antwort eines 10gen (MongoDB) Ingenieurs:

Die beiden Abfragen, die Sie ausführen, sind sehr unterschiedlich. Eine Suchabfrage gibt einen Cursor zurück. Dies ist im Wesentlichen ein Szenario ohne Operation, da keine tatsächlichen Daten zurückgegeben werden (nur die Cursorinformationen). Wenn Sie findOne aufrufen, geben Sie die Daten tatsächlich zurück und schließen den Cursor. Die Dokumente sollten auf jeden Fall klarer sein :-)

pdate : Wenn das Dokument find().limit(1) abgerufen wird, scheinen die Geschwindigkeitsunterschiede um Größenordnungen zu verschwinden. Außerdem konnte ich den großen Geschwindigkeitsunterschied mit dem MongoDB-JavaScript-Treiber nicht reproduzieren. Ich habe ursprünglich ein Benchmarking mit dem MongoDB Java -Treiber) durchgeführt.

34
Leftium

findOne() ist in der Tat syntaktischer Zucker für find().limit(1), , vorausgesetzt, Sie rufen das Dokument tatsächlich ab (im Gegensatz dazu, den Cursor nur mit find() zurückzugeben).

Siehe Antwort von Leftium und Updates für weitere Details.

6
Nick Chammas

Der Quellcode kann sehr hilfreich sein.

Es ist Java, aber ich denke, es kann auch helfen.

Das 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;
}

Und hier ist find()

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

Wie wir sehen können, ruft findOne()find() in sich selbst auf, erhält alle DBOject in i und gibt dann die erste zurück.

3
shellbye