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.