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


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

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.


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

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

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

});  

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.


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.


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

6

C'est ce que j'utilise.

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

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

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

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

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 }) })
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.