Metoda wyszukiwania Mongoose z $ lub warunkiem nie działa poprawnie

116

Ostatnio zacząłem używać MongoDB z Mongoose na Nodejs.

Kiedy używam metody Model.find z $orwarunkiem i _idpolem, Mongoose nie działa poprawnie.

To nie działa:

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

Nawiasem mówiąc, jeśli usunę część „_id”, TO DZIAŁA!

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

W powłoce MongoDB oba działają poprawnie.

Younghan
źródło

Odpowiedzi:

211

Rozwiązałem to przez googlowanie:

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
źródło
2
czy możesz opisać, dlaczego to rozwiązanie działa ze słowami? dzięki
Alexander Mills,
Wygląda to na rozwiązanie dość konkretnego problemu. Być może będziesz musiał szukać dalej.
Kesarion
Czy możesz podać swoje referencje? Dlaczego w tym przypadku parametr musi mieć więcej niż 12 znaków? Czy jest to specyficzne dla Twojego problemu lub wymagania ObjectId ()? Co jeśli mój parametr nie ma 12 znaków? Dzięki!
yusong
6
możesz również sprawdzić ObjectId w następujący sposób:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
Orhan
@yusong, to spowodowane przez mangustę, wyświetli błąd, jeśli nie jest prawidłowym identyfikatorem obiektu. Czystszy sposób na zrobienie tego wspomniany powyżej.
Haydar Ali Ismail
53

Błagam wszystkich o używanie języka konstruktora zapytań Mongoose i obietnic zamiast wywołań zwrotnych:

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

Przeczytaj więcej o zapytaniach Mongoose .

Govind Rai
źródło
Kocham to! Dzięki za ostrzeżenie!
zeckdude
0

Zgodnie z dokumentacją mongoDB: „... Oznacza to, że aby MongoDB używał indeksów do oceny $ lub wyrażenia, wszystkie klauzule w $ lub wyrażeniu muszą być obsługiwane przez indeksy”.

Więc dodaj indeksy dla innych pól i zadziała. Miałem podobny problem i to go rozwiązało.

Możesz przeczytać więcej tutaj: https://docs.mongodb.com/manual/reference/operator/query/or/

Farasi78
źródło
1
to jest błędne stwierdzenie - potrzebujesz indeksów tylko JEŚLI potrzebujesz indeksów do użycia - tj. do wydajności, aby uniknąć skanowania kolekcji. Ale jeśli wydajność nie jest problemem (np. Kolekcja jest dość mała), to nie ma znaczenia ...
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
źródło
1
Czym różni się twoja odpowiedź od odpowiedzi Govinda Rai? Co sprawia, że ​​twój jest lepszy od ich?
BDL
async / await, nic nie czyni go lepszym?
Firez
2
Odpowiedzi zawierające tylko kod są generalnie mile widziane na tej stronie. Czy mógłbyś zmodyfikować swoją odpowiedź, aby zawierała komentarze lub wyjaśnienia dotyczące kodu? Wyjaśnienia powinny odpowiadać na pytania typu: Co to robi? Jak to się dzieje? Dokąd to zmierza? Jak rozwiązuje problem OP? Zobacz: Jak odpowiedzieć . Dzięki!
Eduardo Baitello