La méthode de recherche de Mongoose avec $ ou condition ne fonctionne pas correctement

116

Récemment, j'ai commencé à utiliser MongoDB avec Mongoose sur Nodejs.

Lorsque j'utilise la méthode Model.find avec $orcondition et _idchamp, Mongoose ne fonctionne pas correctement.

Cela ne fonctionne pas:

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

Au fait, si je supprime la partie '_id', cela fonctionne!

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

Et dans le shell MongoDB, les deux fonctionnent correctement.

Younghan
la source

Réponses:

211

Je l'ai résolu en recherchant sur 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
la source
2
pouvez-vous décrire pourquoi cette solution fonctionne avec des mots? merci
Alexander Mills
Cela ressemble à une solution à un problème assez spécifique. Vous devrez peut-être continuer à chercher.
Kesarion
Pourriez-vous fournir votre référence? Pourquoi, dans ce cas, param doit comporter plus de 12 caractères? Est-ce spécifique à votre problème ou à l'exigence d'ObjectId ()? Et si mon paramètre n'a pas 12 caractères? Merci!
yusong
6
vous pouvez également vérifier ObjectId comme suit:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
Orhan
@yusong c'est dû à la mangouste lancera une erreur si ce n'est pas un ObjectId valide. Une façon plus propre de le faire mentionnée ci-dessus.
Haydar Ali Ismail
53

J'implore tout le monde d'utiliser le langage de création de requêtes et les promesses de Mongoose au lieu des rappels:

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

En savoir plus sur les requêtes Mongoose .

Govind Rai
la source
Aimer! Merci pour l'information!
zeckdude le
0

Selon la documentation de mongoDB: "... Autrement dit, pour que MongoDB utilise des index pour évaluer une expression $ or, toutes les clauses de l'expression $ or doivent être supportées par des index."

Ajoutez donc des index pour vos autres champs et cela fonctionnera. J'ai eu un problème similaire et cela l'a résolu.

Vous pouvez en savoir plus ici: https://docs.mongodb.com/manual/reference/operator/query/or/

Farasi78
la source
1
c'est une fausse déclaration - vous n'avez besoin d'index que SI vous avez besoin d'index à utiliser - c'est-à-dire pour les performances, pour éviter une analyse de collection. Mais si les performances ne sont pas un problème (par exemple, la collection est assez petite), alors cela n'a pas d'importance.
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
la source
1
En quoi votre réponse est-elle différente de celle de Govind Rai? Qu'est-ce qui rend le vôtre supérieur au leur?
BDL
async / wait, rien ne le rend supérieur?
Firez le
2
Les réponses au code uniquement sont généralement mal vues sur ce site. Pourriez-vous s'il vous plaît modifier votre réponse pour inclure des commentaires ou une explication de votre code? Les explications doivent répondre à des questions telles que: que fait-il? Comment ça marche? Où est-ce que ça va? Comment résout-il le problème d'OP? Voir: Comment répondre . Merci!
Eduardo Baitello le