Mongoose.js: поиск пользователя по имени пользователя LIKE value

95

Мне нравится искать пользователя в mongoDb, ища пользователя с именем value. Проблема с:

username: 'peter'

в том, что я не нахожу, если имя пользователя - «Питер» или «Питер» .. или что-то в этом роде.

Итак, я хочу сделать как sql

SELECT * FROM users WHERE username LIKE 'peter'

Надеюсь, вы, ребята, получите то, о чем я прошу?

Кратко: 'поле LIKE value' в mongoose.js / mongodb

ПитерБечП
источник
1
Просто в стороне, SQL - запрос будет не найти Peterили PeTERни как LIKEне чувствителен к регистру.
beny23

Ответы:

147

Для тех, кто искал решение, вот оно:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});
ПитерБечП
источник
2
что означает аргумент "я"? Это как-то связано с чувствительностью к регистру?
AzaFromKaza
2
«i» - аргумент для выбора флага поиска. Тогда "i" нечувствителен к регистру. Вы можете прочитать больше об этом здесь. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP
10
Это предполагает, что регулярное выражение недействительно. Если вы, например, добавите «[» в качестве имени пользователя, то вызовет исключение. Просто убедитесь, что вы пытаетесь перехватить или повторно использовать вводимые данные и проверяете [^ a-zA-Z0-9], а затем не продолжаете. В этом случае это просто тестовый ввод, поэтому имеет смысл.
Джейсон Себринг
1
$ = Соответствует концу строки
PeterBechP
1
@JasonSebring Хотя я согласен с тем, что проверка ввода - неплохая идея, лучший подход - это фактический алгоритм экранирования. И исключения - это даже не самая большая проблема, но представьте, что вы использовали аналогичный код на странице входа и пользователя, введенного в ".*"качестве имени пользователя.
Тобиас
78

У меня недавно были проблемы с этим, я использую этот код и у меня все работает нормально.

var data = 'Peter';

db.User.find({'name' : new RegExp(data, 'i')}, function(err, docs){
    cb(docs);
});

Использование напрямую /Peter/iработает, но я использую, '/'+data+'/i'а не работаю для меня.

Донфлопес
источник
Ну, я просто попробовал еще. Я также вижу, если я просто напишу P ?? хммм.
PeterBechP
Да, я использую ajax-петиции для поиска пользователей. Вы можете изменить RegExp.
Donflopez
37
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )
Каномдук
источник
@MikeShi Каков пример этого сценария?
Лен Джозеф
@LenJoseph просто в целом атака ReDoS: owasp.org/index.php/… , я не знаю , уязвим ли мангуст на данный момент, или есть ли какие-либо предполагаемые функции для обнаружения входов ReDoS и дезинфекции их на уровне мангуста.
Майк Ши
14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})
Райнос
источник
что, если значение - var? Как это настроить? / varhere / i?
PeterBechP
2
@PeterBechP создает регулярное выражение: \new RegExp(var, "i")
Raynos
работает нормально .. теперь у меня проблема .. Он должен только найти Питера, если var - Питер. Но если я установлю переменную на 'p', он все равно найдет Питера.
PeterBechP
@PeterBechP затем удалите флаг нечувствительности к регистру: \
Raynos
14
router.route('/product/name/:name')
.get(function(req, res) {

    var regex = new RegExp(req.params.name, "i")
    ,   query = { description: regex };

    Product.find(query, function(err, products) {
        if (err) {
            res.json(err);
        }

        res.json(products);
    });

});  
Victorkurauchi
источник
13

Для этого вам следует использовать регулярное выражение.

db.users.find({name: /peter/i});

Однако будьте осторожны, этот запрос не использует index.

Серджио Тюленцев
источник
9

мангуст док для находки. mongodb doc для регулярного выражения.

var Person = mongoose.model('Person', yourSchema);
// find each person with a name contains 'Ghost'
Person.findOne({ "name" : { $regex: /Ghost/, $options: 'i' } },
    function (err, person) {
             if (err) return handleError(err);
             console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation);
});

Обратите внимание , что первый аргумент мы перейдем к mongoose.findOneфункции: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"этому поле документа , который вы ищете, "Ghost"является регулярным выражением, "i"для случая нечувствительного матча. Надеюсь, что это поможет вам.

Шашит Даршана
источник
какие $ варианты
kabuto178 09
8

Следующий запрос найдет документы с требуемой строкой без учета регистра, а также с глобальным вхождением.

var name = 'Peter';
    db.User.find({name:{
                         $regex: new RegExp(name, "ig")
                     }
                },function(err, doc) {
                                     //Your code here...
              });
разработчик
источник
6

Это то, что я использую.

module.exports.getBookByName = function(name,callback){
    var query = {
            name: {$regex : name}
    }
    User.find(query,callback);
}
Виквинсер
источник
5

Вот мой код с expressJS:

router.route('/wordslike/:word')
    .get(function(request, response) {
            var word = request.params.word;       
            Word.find({'sentence' : new RegExp(word, 'i')}, function(err, words){
               if (err) {response.send(err);}
               response.json(words);
            });
         });
Энрико Гюрин
источник
1

если я хочу запросить всю запись при каком-либо условии , я могу использовать это:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);
индивидуалист
источник
Похоже на ненужное использование того, $regexчто вы могли просто использовать { $exists: true }.
Шон
0

Просто дополняя ответ @PeterBechP.

Не забудьте убрать специальные символы. https://stackoverflow.com/a/6969486

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

var name = 'Peter+with+special+chars';

model.findOne({name: new RegExp('^'+escapeRegExp(name)+'$', "i")}, function(err, doc) {
  //Do your action here..
});
Фелипепасторелима
источник
0

Это мое решение для преобразования каждого значения в req.body в параметр Mongoose LIKE :

let superQ = {}

Object.entries({...req.body}).map((val, i, arr) => {
    superQ[val[0]] = { '$regex': val[1], '$options': 'i' }
})

User.find(superQ)
  .then(result => {
    res.send(result)})
  .catch(err => { 
    res.status(404).send({ msg: err }) })
Соломон Буш
источник