Метод поиска Mongoose с $ или условием не работает должным образом

117

Недавно я начал использовать MongoDB с Mongoose на Nodejs.

Когда я использую метод Model.find с $orусловием и _idполем, Mongoose не работает должным образом.

Это не работает:

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

Кстати, если я удалю часть '_id', это ДЕЙСТВИТЕЛЬНО работает!

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

И в оболочке MongoDB оба работают правильно.

Younghan
источник

Ответы:

213

Я решил это через гугл:

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
источник
2
Вы можете описать словами, почему это решение работает? спасибо
Александр Миллс
Это похоже на решение довольно конкретной проблемы. Возможно, вам придется продолжить поиск.
Kesarion
Не могли бы вы предоставить свою ссылку? Почему в этом случае параметр должен состоять более чем из 12 символов? Это относится к вашей проблеме или требованию ObjectId ()? Что делать, если в моем параметре нет 12 символов? Спасибо!
yusong 02
6
вы также можете проверить ObjectId следующим образом:const mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid(objectidtocheck)
Orhan
@yusong, это из-за того, что мангуст выдаст ошибку, если это неверный ObjectId. Более чистый способ сделать это, упомянутый выше.
Хайдар Али Исмаил
54

Я умоляю всех использовать язык построителя запросов Mongoose и обещания вместо обратных вызовов:

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

Узнайте больше о запросах Mongoose .

Говинд Рай
источник
Любить это! Спасибо за внимание!
zeckdude
0

Согласно документации mongoDB: «... То есть, чтобы MongoDB использовала индексы для оценки выражения $ or, все предложения в выражении $ or должны поддерживаться индексами».

Так что добавьте индексы для других полей, и все заработает. У меня была аналогичная проблема, и это решило ее.

Вы можете прочитать больше здесь: https://docs.mongodb.com/manual/reference/operator/query/or/

Фараси78
источник
1
это неверное утверждение - вам нужны индексы только ЕСЛИ вам нужны индексы, которые будут использоваться, то есть для производительности, чтобы избежать сканирования коллекции. Но если производительность не является проблемой (например, коллекция довольно маленькая), тогда это не имеет значения ..
Энди Лоренц
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
источник
1
Чем ваш ответ отличается от ответа Говинд Рая? Что делает ваш лучше их?
BDL
async / await, ничто не делает его лучше?
Firez
2
Ответы только на код обычно не одобряются на этом сайте. Не могли бы вы отредактировать свой ответ, включив в него некоторые комментарии или пояснения к вашему коду? Разъяснения должны отвечать на такие вопросы, как: Что он делает? Как это сделать? Куда оно девается? Как это решает проблему OP? См .: Как ответить . Спасибо!
Эдуардо Байтелло