O método find do Mongoose com $ ou condição não funciona corretamente


116

Recentemente, comecei a usar o MongoDB com o Mongoose no Nodejs.

Quando eu uso o método Model.find com $orcondição e _idcampo, o Mongoose não funciona corretamente.

Isso não funciona:

User.find({
  $or: [
    { '_id': param },
    { 'name': param },
    { 'nickname': param }
  ]
}, function(err, docs) {
   if(!err) res.send(docs);
});

A propósito, se eu remover a parte '_id', isso FUNCIONA!

User.find({
  $or: [
    { 'name': param },
    { 'nickname': param }
  ]
}, function(err, docs) {
   if(!err) res.send(docs);
});

E no shell do MongoDB, ambos funcionam corretamente.

Respostas:


211

Resolvi isso pesquisando no Google:

var ObjectId = require('mongoose').Types.ObjectId;
var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );
// You should make string 'param' as ObjectId type. To avoid exception, 
// the 'param' must consist of more than 12 characters.

User.find( { $or:[ {'_id':objId}, {'name':param}, {'nickname':param} ]}, 
  function(err,docs){
    if(!err) res.send(docs);
});

2
você pode descrever por que essa solução funciona com palavras? obrigado
Alexander Mills

Isso parece uma solução para um problema bastante específico. Você pode ter que continuar procurando.
Kesarion de

Você poderia fornecer sua referência? Por que, neste caso, o parâmetro deve ter mais de 12 caracteres? Isso é específico ao seu problema ou ao requisito de ObjectId ()? E se meu param não tiver 12 caracteres? Obrigado!
yusong

6
você também pode verificar ObjectId da seguinte forma:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
Orhan

@yusong é devido ao mongoose que lançará um erro se não for um ObjectId válido. Uma maneira mais limpa de fazer isso mencionada acima.
Haydar Ali Ismail

53

Imploro a todos que usem a linguagem de construção de consultas e promessas do Mongoose em vez de callbacks:

User.find().or([{ name: param }, { nickname: param }])
    .then(users => { /*logic here*/ })
    .catch(error => { /*error logic here*/ })

Leia mais sobre as consultas do Mongoose .


Adoro! Obrigado pelo aviso!
zeckdude

0

De acordo com a documentação do mongoDB: "... Ou seja, para o MongoDB usar índices para avaliar um $ ou expressão, todas as cláusulas em $ ou expressão devem ser suportadas por índices."

Portanto, adicione índices para seus outros campos e isso funcionará. Eu tive um problema semelhante e isso resolveu.

Você pode ler mais aqui: https://docs.mongodb.com/manual/reference/operator/query/or/


1
esta é uma declaração errada - você só precisa de índices SE precisar que eles sejam usados ​​- ou seja, para desempenho, para evitar uma varredura de coleção. Mas se o desempenho não for um problema (por exemplo, a coleção é muito pequena), então não importa.
Andy Lorenz

0
async() => {
let body = await model.find().or([
  { name: 'something'},
  { nickname: 'somethang'}
]).exec();
console.log(body);
}
/* Gives an array of the searched query!
returns [] if not found */

1
Qual a diferença entre a sua resposta e a de Govind Rai? O que torna o seu superior ao deles?
BDL

async / await, nada o torna superior?
Firez

2
Respostas apenas em código são geralmente desaprovadas neste site. Você poderia editar sua resposta para incluir alguns comentários ou explicações sobre seu código? As explicações devem responder a perguntas como: O que isso faz? Como isso faz? Onde isso vai? Como isso resolve o problema do OP? Veja: Como responder . Obrigado!
Eduardo Baitello
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.