El método de búsqueda de Mongoose con $ o condición no funciona correctamente


116

Recientemente comencé a usar MongoDB con Mongoose en Nodejs.

Cuando utilizo el método Model.find con $orcondición y _idcampo, Mongoose no funciona correctamente.

Esto no funciona:

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

Por cierto, si elimino la parte '_id', ¡esto SÍ funciona!

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

Y en el shell de MongoDB, ambos funcionan correctamente.

Respuestas:


211

Lo resolví buscando en 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
¿Puede describir por qué esta solución funciona con palabras? gracias
— Alexander Mills

Esto parece una solución a un problema bastante específico. Puede que tengas que seguir buscando.
— Kesarion

¿Podría darnos su referencia? ¿Por qué en este caso param tiene que tener más de 12 caracteres? ¿Es esto específico para su problema o el requisito de ObjectId ()? ¿Qué pasa si mi parámetro no tiene 12 caracteres? ¡Gracias!
— yusong

6
También puede verificar ObjectId de la siguiente manera:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
— Orhan

@yusong se debe a que la mangosta arrojará un error si no es un ObjectId válido. Una forma más limpia de hacerlo mencionada anteriormente.
— Haydar Ali Ismail

53

Les imploro a todos que usen el lenguaje y las promesas del generador de consultas de Mongoose en lugar de las devoluciones de llamada:

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

Leer más sobre Mongoose Queries .


¡Quiéralo! ¡Gracias por el aviso!
— zeckdude

0

Según la documentación de mongoDB: "... Es decir, para que MongoDB utilice índices para evaluar una expresión $ o, todas las cláusulas de la expresión $ o deben ser compatibles con índices".

Así que agregue índices para sus otros campos y funcionará. Tuve un problema similar y esto lo resolvió.

Puede leer más aquí: https://docs.mongodb.com/manual/reference/operator/query/or/


1
esta es una declaración incorrecta - solo necesita índices SI necesita que se utilicen índices - es decir, para el rendimiento, para evitar un escaneo de colección. Pero si el rendimiento no es un problema (por ejemplo, la colección es bastante pequeña), entonces no 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
¿En qué se diferencia su respuesta de la de Govind Rai? ¿Qué hace que el tuyo sea superior al de ellos?
— BDL

async / await, ¿nada lo hace superior?
— Firez

2
Las respuestas de solo código generalmente están mal vistas en este sitio. ¿Podría editar su respuesta para incluir algunos comentarios o una explicación de su código? Las explicaciones deben responder preguntas como: ¿Qué hace? ¿Cómo lo hace? ¿A dónde va? ¿Cómo resuelve el problema de OP? Ver: Cómo responder . ¡Gracias!
— Eduardo Baitello
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.