Die Suchmethode von Mongoose mit $ oder Bedingung funktioniert nicht richtig

116

Vor kurzem benutze ich MongoDB mit Mongoose auf Nodejs.

Wenn ich die Model.find-Methode mit $orBedingung und _idFeld verwende, funktioniert Mongoose nicht richtig.

Das funktioniert nicht:

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

Übrigens, wenn ich den Teil '_id' entferne, funktioniert das!

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

Und in der MongoDB-Shell funktionieren beide ordnungsgemäß.

Younghan
quelle

Antworten:

211

Ich habe es durch googeln gelöst:

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
quelle
2
Können Sie beschreiben, warum diese Lösung mit Worten funktioniert? danke
Alexander Mills
Dies scheint eine Lösung für ein ziemlich spezifisches Problem zu sein. Möglicherweise müssen Sie weiter suchen.
Kesarion
Könnten Sie Ihre Referenz angeben? Warum muss param in diesem Fall mehr als 12 Zeichen enthalten? Ist dies spezifisch für Ihr Problem oder die Anforderung von ObjectId ()? Was ist, wenn mein Parameter keine 12 Zeichen hat? Vielen Dank!
Yusong
6
Sie können ObjectId auch wie folgt überprüfen:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
Orhan
@yusong es liegt daran, dass Mungo einen Fehler auslöst, wenn es sich nicht um eine gültige ObjectId handelt. Ein sauberer Weg, es zu tun, der oben erwähnt wurde.
Haydar Ali Ismail
53

Ich bitte alle, die Sprache und die Versprechen von Mongoose anstelle von Rückrufen zu verwenden:

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

Lesen Sie mehr über Mungo-Abfragen .

Govind Rai
quelle
Liebe es! Danke für die Warnung!
Zeckdude
0

Laut mongoDB-Dokumentation: "... Damit MongoDB Indizes zum Auswerten eines $ oder Ausdrucks verwenden kann, müssen alle Klauseln im $ oder Ausdruck von Indizes unterstützt werden."

Fügen Sie also Indizes für Ihre anderen Felder hinzu, und es wird funktionieren. Ich hatte ein ähnliches Problem und das löste es.

Weitere Informationen finden Sie hier: https://docs.mongodb.com/manual/reference/operator/query/or/

Farasi78
quelle
1
Dies ist eine falsche Aussage - Sie benötigen nur Indizes, wenn Indizes verwendet werden müssen - dh für die Leistung, um einen Sammlungsscan zu vermeiden. Aber wenn Leistung kein Problem ist (z. B. die Sammlung ist ziemlich klein), spielt es keine Rolle.
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
quelle
1
Wie unterscheidet sich Ihre Antwort von der von Govind Rai? Was macht deine überlegen?
BDL
async / warten, nichts macht es überlegen?
Firez
2
Nur-Code-Antworten werden auf dieser Website im Allgemeinen verpönt. Könnten Sie bitte Ihre Antwort bearbeiten, um einige Kommentare oder Erklärungen zu Ihrem Code aufzunehmen? Erklärungen sollten Fragen beantworten wie: Was macht es? Wie macht es das? Wo geht es hin? Wie löst es das Problem von OP? Siehe: Antworten . Vielen Dank!
Eduardo Baitello