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.