Mongoose.js: znajdź użytkownika według wartości LIKE nazwy użytkownika

95

Lubię szukać użytkownika w mongoDb, szukając użytkownika o nazwie value. Problem z:

username: 'peter'

jest to, że nie znajduję go, jeśli nazwa użytkownika to „Peter”, „PeTER”… lub coś w tym rodzaju.

Więc chcę robić jak sql

SELECT * FROM users WHERE username LIKE 'peter'

Mam nadzieję, że dostaniecie to, o co proszę?

Skrót: „wartość pola LIKE” w mongoose.js / mongodb

PeterBechP
źródło
1
Tak na marginesie, zapytanie SQL nie może znaleźć Peterlub PeTERteż LIKEnie jest rozróżniające wielkość liter.
beny 23

Odpowiedzi:

147

Dla tych, którzy szukali rozwiązania tutaj jest:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});
PeterBechP
źródło
2
co oznacza argument „i”? Czy ma to coś wspólnego z rozróżnianiem wielkości liter?
AzaFromKaza,
2
„i” jest argumentem wyboru flagi wyszukiwania. „i” jest wtedy bez rozróżniania wielkości liter. Więcej na ten temat przeczytasz tutaj. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/ ...
PeterBechP
10
Zakłada się, że wyrażenie regularne nie jest nieprawidłowe. Jeśli na przykład dodasz „[” jako nazwę użytkownika, zostanie zgłoszony wyjątek. Po prostu upewnij się, że próbujesz przechwycić lub regexing swoje dane wejściowe przed sprawdzeniem [^ a-zA-Z0-9], a następnie nie kontynuujesz. W tym przypadku tylko testowe wejście ma sens.
Jason Sebring
1
$ = Dopasuj koniec ciągu
PeterBechP
1
@JasonSebring Chociaż zgadzam się, że walidacja danych wejściowych nie jest złym pomysłem, najlepszym podejściem jest faktyczny algorytm ucieczki. A wyjątki nie są nawet najgorszym problemem, ale wyobraź sobie, że użyłeś podobnego kodu na stronie logowania, a użytkownik wprowadził ".*"jako nazwę użytkownika.
Tobias,
78

Ostatnio miałem z tym problemy, używam tego kodu i działa dobrze.

var data = 'Peter';

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

Używaj bezpośrednio /Peter/ipracy, ale używam '/'+data+'/i'i nie działa dla mnie.

Donflopez
źródło
Cóż, po prostu spróbowałem tego jeszcze trochę. Widzę to również stwierdzam, czy po prostu napiszę P ?? hmmm.
PeterBechP
Tak, używam petycji Ajax do wyszukiwania użytkowników. Możesz zmodyfikować RegExp.
Donflopez
37
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )
Kanomdook
źródło
@MikeShi Jaki jest przykładowy scenariusz?
Len Joseph
@LenJoseph tylko ogólnie atak ReDoS: owasp.org/index.php/… , nie wiem, czy w tym momencie mangusta jest podatna na ataki, lub czy istnieje jakakolwiek zamierzona funkcja wykrywania wejść ReDoS i odkażania ich na poziomie mangusty.
Mike Shi
14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})
Raynos
źródło
co, jeśli wartość jest zmienną? Jak to ustawić? / varhere / i?
PeterBechP
2
@PeterBechP konstruuje wyrażenie regularne: \new RegExp(var, "i")
Raynos
działa dobrze .. teraz mam problem .. Muszę tylko znaleźć petera, jeśli var to peter. Ale jeśli ustawię var na „p”, nadal będzie znajdował petera.
PeterBechP
@PeterBechP następnie usuń flagę niewrażliwości na wielkość liter: \
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);
    });

});  
vicorkurauchi
źródło
13

W tym celu należy użyć wyrażenia regularnego.

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

Uważaj jednak, ponieważ to zapytanie nie używa indeksu.

Sergio Tulentsev
źródło
9

dokument mangusty do znalezienia. mongodb doc dla wyrażenia regularnego.

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);
});

Uwaga pierwszy argument przechodzimy do mongoose.findOnefunkcji: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"jest pole dokumentu, którego szukasz, "Ghost"jest wyrażenie regularne, "i"jest wielkość liter nieczuły. Mam nadzieję, że to ci pomoże.

Shashith Darshana
źródło
jakie są opcje $
kabuto178
8

Następujące zapytanie znajdzie dokumenty z wymaganą wielkością liter bez rozróżniania, a także z wystąpieniem globalnym

var name = 'Peter';
    db.User.find({name:{
                         $regex: new RegExp(name, "ig")
                     }
                },function(err, doc) {
                                     //Your code here...
              });
prodeveloper
źródło
6

Tego właśnie używam.

module.exports.getBookByName = function(name,callback){
    var query = {
            name: {$regex : name}
    }
    User.find(query,callback);
}
vikvincer
źródło
5

Tutaj mój kod z 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);
            });
         });
Enrico Giurin
źródło
1

jeśli chcę odpytać wszystkie rekordy w pewnych warunkach , mogę użyć tego:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);
politycznie niezależny
źródło
Wydaje się, że niepotrzebne jest użycie, $regexkiedy mogłeś właśnie użyć { $exists: true }.
sean
0

To tylko uzupełnienie odpowiedzi @PeterBechP.

Nie zapomnij o zmianie specjalnych znaków. 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..
});
felipepastorelima
źródło
0

Oto moje rozwiązanie do konwersji każdej wartości w req.body na parametr LIKE mongoose :

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 }) })
Solomon Bush
źródło