mongodb / mongoose findMany - recherche tous les documents dont les ID sont répertoriés dans le tableau

246

J'ai un tableau de _ids et je veux obtenir tous les documents en conséquence, quelle est la meilleure façon de le faire?

Quelque chose comme ...

// doesn't work ... of course ...

model.find({
    '_id' : [
        '4ed3ede8844f0f351100000c',
        '4ed3f117a844e0471100000d', 
        '4ed3f18132f50c491100000e'
    ]
}, function(err, docs){
    console.log(docs);
});

Le tableau peut contenir des centaines de _ids.

ezmilhouse
la source

Réponses:

479

La findfonction dans mangouste est une requête complète à mongoDB. Cela signifie que vous pouvez utiliser la $inclause mongoDB pratique , qui fonctionne exactement comme la version SQL de la même chose.

model.find({
    '_id': { $in: [
        mongoose.Types.ObjectId('4ed3ede8844f0f351100000c'),
        mongoose.Types.ObjectId('4ed3f117a844e0471100000d'), 
        mongoose.Types.ObjectId('4ed3f18132f50c491100000e')
    ]}
}, function(err, docs){
     console.log(docs);
});

Cette méthode fonctionnera bien même pour les tableaux contenant des dizaines de milliers d'identifiants. (Voir Déterminer efficacement le propriétaire d'un enregistrement )

Je recommanderais à toute personne travaillant avec de mongoDBlire la section Requêtes avancées des excellents documents officiels mongoDB

Daniel Mendel
la source
9
Un peu tard pour cette discussion, mais comment vous assurer que l'ordre des éléments retournés correspond à l'ordre du tableau des éléments que vous fournissez dans le tableau? Les documents ne sont pas garantis pour sortir dans n'importe quel ordre sauf si vous spécifiez un tri. Et si vous voulez les trier dans le même ordre que vous les listez dans le tableau (par exemple ... 000c, ... 000d, ... 000e)?
Kevin
7
Cela n'a pas fonctionné pour une raison quelconque. J'ai un tableau vide de documents
chovy
2
@chovy essayez d'abord de les convertir en ObjectIds , au lieu de passer des chaînes.
Georgi Hristozov
@GeorgiHristozov J'utilise un générateur d'ID personnalisé ... la conversion en ObjectId fonctionne-t-elle toujours? (mangouste + shortid)
chovy
1
@Schybo qui ne fait absolument aucune différence. { _id : 5 }est le même que { '_id' : 5 }.
royhowie
29

Ids est le tableau des ID d'objet:

const ids =  [
    '4ed3ede8844f0f351100000c',
    '4ed3f117a844e0471100000d', 
    '4ed3f18132f50c491100000e',
];

Utilisation de Mongoose avec rappel:

Model.find().where('_id').in(ids).exec((err, records) => {});

Utilisation de Mongoose avec la fonction asynchrone:

records = await Model.find().where('_id').in(ids).exec();

N'oubliez pas de changer de modèle avec votre modèle actuel.

SnnSnn
la source
Cela devrait être la réponse acceptée car elle est la plus à jour et la plus cohérente. Vous n'avez pas besoin de convertir les identifiants en ObjectId comme dans la réponse acceptée, et il utilise les requêtes de style impératif mangouste . Merci btw!
Javi Marzán
Ceci est une méthode très propre et mise à jour, si cela ne vous dérange pas, je voudrais poser quelques questions, si j'ai un tableau de références ObjectIdcomme celui ci-dessus (disons, j'ai des projets et j'ai assigné un tableau de projets à certains utilisateurs avec le project_id référencé sur le modèle utilisateur), si je supprime un projet, comment puis-je m'assurer qu'il idest supprimé du tableau référencé à partir du modèle utilisateur? Merci tapis.
Eazy
10

Utilisez ce format d'interrogation

let arr = _categories.map(ele => new mongoose.Types.ObjectId(ele.id));

Item.find({ vendorId: mongoose.Types.ObjectId(_vendorId) , status:'Active'})
  .where('category')
  .in(arr)
  .exec();
Derese Getachew
la source
4

Node.js et MongoChef me forcent à convertir en ObjectId. C'est ce que j'utilise pour récupérer une liste d'utilisateurs de la base de données et récupérer quelques propriétés. Faites attention à la conversion de type à la ligne 8.

// this will complement the list with userName and userPhotoUrl based on userId field in each item
augmentUserInfo = function(list, callback){
        var userIds = [];
        var users = [];         // shortcut to find them faster afterwards
        for (l in list) {       // first build the search array
            var o = list[l];
            if (o.userId) {
                userIds.push( new mongoose.Types.ObjectId( o.userId ) );           // for the Mongo query
                users[o.userId] = o;                                // to find the user quickly afterwards
            }
        }
        db.collection("users").find( {_id: {$in: userIds}} ).each(function(err, user) {
            if (err) callback( err, list);
            else {
                if (user && user._id) {
                    users[user._id].userName = user.fName;
                    users[user._id].userPhotoUrl = user.userPhotoUrl;
                } else {                        // end of list
                    callback( null, list );
                }
            }
        });
    }
Nico
la source
7
userIds = _.map (list, function (userId) {return mongoose.Types.ObjectId (userId)};
Michael Draper
1
Je n'ai pas eu à convertir en ObjectID à l'aide de mangouste 4.5.9.
Florian Wendelborn