mongodb / mongoose findMany - encontra todos os documentos com IDs listados na matriz

246

Eu tenho uma variedade de _ids e quero obter todos os documentos de acordo. Qual é a melhor maneira de fazer isso?

Algo como ...

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

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

A matriz pode conter centenas de _ids.

ezmilhouse
fonte

Respostas:

479

A findfunção no mongoose é uma consulta completa ao mongoDB. Isso significa que você pode usar a útil $incláusula mongoDB , que funciona exatamente como a versão SQL da mesma.

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

Esse método funcionará bem mesmo para matrizes contendo dezenas de milhares de IDs. (Consulte Determinar com eficiência o proprietário de um registro )

Eu recomendaria que qualquer pessoa que trabalha com mongoDBleu a seção Consultas avançadas dos excelentes Documentos Oficiais do mongoDB

Daniel Mendel
fonte
9
Meio atrasado para esta discussão, mas como você garantiria que a ordem dos itens retornados corresponda à ordem da matriz de itens que você fornece na matriz? Os documentos não têm garantia de saída em nenhuma ordem, a menos que você especifique uma classificação. E se você os quiser classificados na mesma ordem em que são listados na matriz (por exemplo, ... 000c, ... 000d, ... 000e)?
30714 Kevin
7
Isso não funcionou por algum motivo. Eu tenho uma matriz vazia de docs
Chovy
2
@chovy tente convertê-los em ObjectIds primeiro, em vez de passar as strings.
Georgi Hristozov 02/12/2014
@GeorgiHristozov estou usando um gerador de identificação personalizado ... a conversão para ObjectId ainda funciona? (mangusto + shortid)
chovy
1
@ Schybo que não faz absolutamente nenhuma diferença. { _id : 5 }é o mesmo que { '_id' : 5 }.
precisa saber é o seguinte
27

Ids é a matriz de IDs de objetos:

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

Usando o Mongoose com retorno de chamada:

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

Usando o Mongoose com função assíncrona:

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

Não se esqueça de alterar o modelo com seu modelo atual.

SnnSnn
fonte
Essa deve ser a resposta aceita, pois é a mais atualizada e coerente. Você não precisa converter os IDs em ObjectId, como na resposta aceita, e ele usa as consultas de estilo imperativo do mangusto . Obrigado btw!
Javi Marzán 15/03
Este é um método muito limpo e atualizado. Se você não se importa, eu gostaria de fazer algumas perguntas, se eu tiver uma variedade de referências ObjectIdcomo a acima (por exemplo, eu tenho projetos e designei uma variedade de projetos para determinados usuários com o project_id mencionado no modelo de usuário), se eu excluir um projeto, como posso garantir que ele idseja excluído da matriz referenciada no modelo de usuário? Obrigado 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
fonte
4

O node.js e o MongoChef me forçam a converter em ObjectId. É isso que eu uso para pegar uma lista de usuários do banco de dados e buscar algumas propriedades. Observe a conversão de tipo na linha 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
fonte
7
userIds = _.map (lista, função (userId) {return mongoose.Types.ObjectId (userId)};;
Michael Draper
1
Não precisei converter para o ObjectID usando o mangusto 4.5.9.
Florian Wendelborn