mongodb / mongoose findMany: busca todos los documentos con ID enumerados en la matriz

246

Tengo una variedad de _ids y quiero obtener todos los documentos en consecuencia, ¿cuál es la mejor manera de hacerlo?

Algo como ...

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

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

La matriz puede contener cientos de _ids.

ezmilhouse
fuente

Respuestas:

479

La findfunción en mongoose es una consulta completa a mongoDB. Esto significa que puede usar la práctica $incláusula mongoDB , que funciona igual que la versión SQL de la misma.

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

Este método funcionará bien incluso para matrices que contienen decenas de miles de identificadores. (Consulte Determinar eficientemente el propietario de un registro )

Recomendaría que cualquiera que trabaje mongoDBlea la sección de Consultas avanzadas de los excelentes Documentos oficiales de mongoDB

Daniel Mendel
fuente
99
Un poco tarde para esta discusión, pero ¿cómo se aseguraría de que el orden de los elementos devueltos coincida con el orden de la matriz de elementos que proporciona en la matriz? No se garantiza que los documentos salgan en ningún orden a menos que especifique un tipo. ¿Qué sucede si desea ordenarlos en el mismo orden en que los enumera en la matriz (por ejemplo, ... 000c, ... 000d, ... 000e)?
Kevin
77
Esto no funcionó por alguna razón. Tengo un conjunto vacío de documentos
chovy
2
@chovy intente convertirlos primero a ObjectIds , en lugar de pasar cadenas.
Georgi Hristozov
@GeorgiHristozov Estoy usando un generador de identificación personalizado ... ¿sigue funcionando la conversión a ObjectId? (mangosta + shortid)
chovy
1
@Schybo que no hace absolutamente ninguna diferencia. { _id : 5 }es el mismo que { '_id' : 5 }.
royhowie
27

Ids es la matriz de identificadores de objeto:

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

Usando Mangosta con devolución de llamada:

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

Usando Mongoose con la función asíncrona:

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

No olvides cambiar el modelo con tu modelo real.

SnnSnn
fuente
Esta debería ser la respuesta aceptada, ya que es la más actualizada y coherente. No tiene que convertir los identificadores a ObjectId como en la respuesta aceptada, y utiliza las consultas de estilo imperativo mangosta . Gracias por cierto!
Javi Marzán
Este es un método muy limpio y actualizado, si no le importa, me gustaría hacer algunas preguntas, si tengo una serie de referencias ObjectIdcomo las anteriores (por ejemplo, tengo proyectos y asigné una serie de proyectos para ciertos usuarios con el project_id referenciado en el modelo de usuario), si elimino un proyecto, ¿cómo me aseguro de que idse elimine de la matriz referenciada desde el modelo de usuario? Gracias mat.
Eazy
9

Use este formato de consulta

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
fuente
4

Tanto node.js como MongoChef me obligan a convertir a ObjectId. Esto es lo que uso para obtener una lista de usuarios de la base de datos y obtener algunas propiedades. Tenga en cuenta la conversión de tipo en la línea 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
fuente
77
userIds = _.map (list, function (userId) {return mongoose.Types.ObjectId (userId)};
Michael Draper el
1
No tuve que convertir a ObjectID usando mongoose 4.5.9.
Florian Wendelborn