Mongoose.js: Rechercher l'utilisateur par nom d'utilisateur LIKE value

95

J'aime aller trouver un utilisateur dans mongoDb en recherchant un utilisateur appelé value. Le problème avec:

username: 'peter'

est que je ne le trouve pas si le nom d'utilisateur est "Peter", ou "PeTER" .. ou quelque chose comme ça.

Alors je veux faire comme SQL

SELECT * FROM users WHERE username LIKE 'peter'

J'espère que vous avez ce que je vous demande?

Short: 'field LIKE value' dans mongoose.js / mongodb

PeterBechP
la source
1
Juste un aparté, la requête SQL ne trouverait pas Peterou PeTERnon plus car elle LIKEn'est pas insensible à la casse.
beny23

Réponses:

144

Pour ceux qui cherchaient une solution, voici:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});
PeterBechP
la source
2
que signifie l'argument "i"? Cela a-t-il quelque chose à voir avec la sensibilité à la casse?
AzaFromKaza
2
"i" est un argument pour choisir un indicateur de recherche. "i" est alors pour insensible à la casse. Vous pouvez en savoir plus ici. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP
10
Cela suppose que l'expression régulière n'est pas invalide. Si vous ajoutez "[" comme nom d'utilisateur par exemple, lèvera une exception. Assurez-vous simplement que vous essayez de capturer ou de regexer votre entrée avant de vérifier [^ a-zA-Z0-9], puis de ne pas continuer. Dans ce cas, sa juste entrée de test est donc logique.
Jason Sebring
1
$ = Correspond à la fin de la chaîne
PeterBechP
1
@JasonSebring Bien que je convienne que la validation d'entrée n'est pas une mauvaise idée, la meilleure approche est un algorithme d'échappement réel. Et les exceptions ne sont même pas le pire problème, mais imaginez que vous avez utilisé un code similaire sur une page de connexion et un utilisateur saisi ".*"comme nom d'utilisateur.
Tobias
79

J'ai eu des problèmes avec cela récemment, j'utilise ce code et fonctionne très bien pour moi.

var data = 'Peter';

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

Utilisez directement le /Peter/itravail, mais j'utilise '/'+data+'/i'et ne fonctionne pas pour moi.

Donflopez
la source
Eh bien, j'ai juste essayé un peu plus. Je le vois aussi trouver si j'écris juste P ?? hmmm.
PeterBechP
Oui, j'utilise pour les pétitions ajax pour rechercher des utilisateurs. Vous pouvez modifier le RegExp.
Donflopez
36
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )
Kanomdook
la source
@MikeShi Quel est un exemple de scénario?
Len Joseph
@LenJoseph juste en général l'attaque ReDoS: owasp.org/index.php/… , je ne sais pas si la mangouste est vulnérable à ce stade, ou s'il existe une fonctionnalité destinée à détecter les entrées ReDoS et à les désinfecter au niveau de la mangouste.
Mike Shi
14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})
Raynos
la source
et si la valeur est un var? Comment mettre en place cela? / varhere / i?
PeterBechP
2
@PeterBechP construit une expression régulière: \new RegExp(var, "i")
Raynos
fonctionne bien .. maintenant j'ai un problème .. Il suffit de trouver peter si le var est peter. Mais si je règle le var sur «p», il trouvera toujours peter.
PeterBechP
@PeterBechP puis supprimez l'indicateur d'insensibilité à la casse: \
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
la source
13

Vous devriez utiliser une regex pour cela.

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

Méfiez-vous cependant que cette requête n'utilise pas d'index.

Sergio Tulentsev
la source
9

mangouste doc pour trouver. mongodb doc pour regex.

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

Notez le premier argument que nous passons à la mongoose.findOnefonction: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"est le champ du document que vous êtes à la recherche, "Ghost"est l'expression régulière, "i"est pour la casse insensible. J'espère que ceci vous aidera.

Shashith Darshana
la source
quelles sont les options $
kabuto178
8

La requête suivante trouvera les documents avec la chaîne requise insensible à la casse et avec une occurrence globale également

var name = 'Peter';
    db.User.find({name:{
                         $regex: new RegExp(name, "ig")
                     }
                },function(err, doc) {
                                     //Your code here...
              });
développeur
la source
6

C'est ce que j'utilise.

module.exports.getBookByName = function(name,callback){
    var query = {
            name: {$regex : name}
    }
    User.find(query,callback);
}
Vikvincer
la source
5

Voici mon code avec 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
la source
1

si je veux interroger tous les enregistrements à certaines conditions, je peux utiliser ceci:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);
Maverick
la source
Cela semble être une utilisation inutile du $regexmoment où vous auriez pu simplement l'utiliser { $exists: true }.
sean
0

Juste en complément de la réponse de @PeterBechP.

N'oubliez pas de scaper les caractères spéciaux. 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
la source
0

C'est ma solution pour convertir chaque valeur d'un req.body en un paramètre de type mangouste 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 }) })
Salomon Bush
la source