Mongoose.js: trova l'utente in base al valore LIKE del nome utente


94

Mi piace cercare un utente in mongoDb cercando un utente chiamato valore. Il problema con:

username: 'peter'

è che non lo trovo se il nome utente è "Peter", o "PeTER" .. o qualcosa del genere.

Quindi voglio fare come sql

SELECT * FROM users WHERE username LIKE 'peter'

Spero che voi ragazzi capiate cosa sto chiedendo?

Breve: "field LIKE value" in mongoose.js / mongodb


1
Solo un a parte, la query SQL sarebbe non trovare Petero PeTERsia come LIKEnon è case-insensitive.
beny23

Risposte:


143

Per chi cercava una soluzione eccola:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});

2
cosa significa l'argomento "i"? Ha qualcosa a che fare con la distinzione tra maiuscole e minuscole?
AzaFromKaza

2
"i" è un argomento per scegliere un flag di ricerca. "i" quindi sta per case-insensitive. Puoi leggere di più al riguardo qui. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP

10
Ciò presuppone che la regex non sia valida. Ad esempio, se aggiungi "[" come nome utente, verrà generata un'eccezione. Assicurati solo di provare a catturare o regexare il tuo input prima e di controllare [^ a-zA-Z0-9], quindi di non procedere. In questo caso, è solo un input di test quindi ha senso.
Jason Sebring

1
$ = Corrisponde alla fine della stringa
PeterBechP

1
@JasonSebring Anche se sono d'accordo che la convalida dell'input non è una cattiva idea, l'approccio migliore è un vero algoritmo di escape. E le eccezioni non sono nemmeno il problema peggiore, ma immagina di aver utilizzato un codice simile su una pagina di accesso e un utente inserito ".*"come nome utente.
Tobias

79

Ho avuto problemi con questo di recente, uso questo codice e funziona bene per me.

var data = 'Peter';

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

Uso direttamente /Peter/ilavoro, ma io uso '/'+data+'/i'e non lavoro per me.


Beh, l'ho provato ancora un po '. Lo vedo anche se scrivo solo P ?? hmmm.
PeterBechP

Sì, uso per le petizioni ajax per cercare gli utenti. Puoi modificare RegExp.
Donflopez

35
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )

@MikeShi Qual è uno scenario di esempio di questo?
Len Joseph,

@LenJoseph solo in generale l'attacco ReDoS: owasp.org/index.php/… , non sono a conoscenza se la mangusta è vulnerabile a questo punto, o se esiste una funzionalità prevista per rilevare gli input ReDoS e disinfettarli a livello di mangusta.
Mike Shi,

14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})

cosa succede se il valore è una variabile? Come configurarlo? / varhere / i?
PeterBechP

2
@PeterBechP crea un'espressione regolare: \new RegExp(var, "i")
Raynos

funziona bene .. ora ho un problema .. Deve solo trovare Peter se il var è Peter. Ma se imposto il var a 'p' troverà ancora peter.
PeterBechP

@PeterBechP quindi rimuove il flag di insensibilità al maiuscolo / minuscolo: \
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

Dovresti usare una regex per questo.

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

Fai attenzione, tuttavia, che questa query non utilizza index.


9

doc mongoose per trovare. mongodb doc per 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);
});

Si noti il primo argomento si passa alla mongoose.findOnefunzione di: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"è il campo del documento che si sta cercando, "Ghost"è l'espressione regolare, "i"è per tra maiuscole e minuscole. Spero che questo ti possa aiutare.


quali sono le $ opzioni
kabuto178

8

La seguente query troverà i documenti con le maiuscole / minuscole richieste in modo insensibile e anche con occorrenza globale

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

6

Questo è quello che sto usando.

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

5

Qui il mio codice con 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

se voglio interrogare tutti i record in qualche condizione, posso usare questo:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);

Sembra un uso non necessario di $regexquando avresti potuto usarlo { $exists: true }.
sean

0

Sto solo completando la risposta di @PeterBechP.

Non dimenticare di scappare i caratteri speciali. 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

Questa è la mia soluzione per convertire ogni valore in un req.body in un parametro LIKE di mangusta :

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 }) })
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.