web-dev-qa-db-fra.com

Différence entre les appels find et findone de MongoDB

Je travaille sur un projet et je ne sais pas s'il existe une différence entre le fonctionnement du curseur find et le fonctionnement du curseur findOne. FindOne est-il juste un wrapper pour find().limit(1)? Je le cherchais et peut-être que quelqu'un sait si mongodb a une méthode spéciale pour cela ou non. Je travaille avec l'API PHP pour mongodb si cela fait une différence.

35
WojonsTech

Basé sur mes propres repères, find().limit(1) est des ordres de grandeur plus rapide que findOne().

Il y a soit une erreur dans la documentation MongoDB, soit un bogue dans findOne(). findOne() fonctionne plus comme find().limit(N) où N est le nombre de documents que la requête retournerait. J'ai compris cela en essayant de comprendre pourquoi mes requêtes simples étaient si lentes!

pdate: réponse d'un ingénieur 10gen (MongoDB):

Les deux requêtes que vous exécutez sont très différentes. Une requête de recherche renvoie un curseur, il s'agit essentiellement d'un scénario sans opération, car aucune donnée réelle n'est renvoyée (uniquement les informations du curseur). Si vous appelez findOne, vous retournez en fait les données et fermez le curseur. Les documents devraient certainement être plus clairs :-)

pdate: En effet, si le document find().limit(1) est récupéré, la différence de vitesse des ordres de grandeur semble disparaître. De plus, je n'ai pas pu reproduire la différence de vitesse majeure avec le pilote JavaScript MongoDB. J'ai à l'origine testé en utilisant le pilote MongoDB Java driver.

34
Leftium

findOne() est en effet sucre syntaxique pour find().limit(1), étant donné que vous récupérez réellement le document (par opposition au simple retour du curseur avec find()).

Voir réponse de Leftium et mises à jour pour plus de détails.

6
Nick Chammas

Le code source peut être très utile.

C'est Java mais je suppose que cela peut aussi aider.

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

Et voici find()

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

Comme nous pouvons voir que findOne() appelle find() en lui-même, obtient tous les DBOject dans i puis retourne le premier.

3
shellbye