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.

Younghan
fuente

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);
});
Younghan
fuente
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 .

Govind Rai
fuente
¡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/

Farasi78
fuente
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 */
Firez
fuente
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