Mongoose.js: buscar usuario por nombre de usuario LIKE valor

95

Me gusta ir a buscar un usuario en mongoDb buscando un usuario llamado valor. El problema con:

username: 'peter'

es que no lo encuentro si el nombre de usuario es "Peter", o "Peter" .. o algo así.

Entonces quiero hacer como sql

SELECT * FROM users WHERE username LIKE 'peter'

¿Espero que obtengan lo que estoy pidiendo?

Corto: 'campo LIKE value' en mongoose.js / mongodb

PeterBechP
fuente
1
Solo un aparte, la consulta SQL no encontraría Petero PeTERtampoco, ya que LIKEno distingue entre mayúsculas y minúsculas.
beny23

Respuestas:

144

Para aquellos que buscaban una solución aquí está:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});
PeterBechP
fuente
2
¿Qué significa el argumento "yo"? ¿Tiene algo que ver con la distinción entre mayúsculas y minúsculas?
AzaFromKaza
2
"i" es un argumento para elegir una bandera de búsqueda. "i" entonces es para mayúsculas y minúsculas. Puedes leer más sobre esto aquí. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP
10
Esto supone que la expresión regular no es válida. Si agrega "[" como nombre de usuario, por ejemplo, arrojará una excepción. Solo asegúrese de estar intentando capturar o regexing su entrada antes y verificar [^ a-zA-Z0-9] y luego no continuar. En este caso, es solo una entrada de prueba, por lo que tiene sentido.
Jason Sebring
1
$ = Coincide con el final de la cadena
PeterBechP
1
@JasonSebring Aunque estoy de acuerdo en que la validación de entrada no es una mala idea, el mejor enfoque es un algoritmo de escape real. Y las excepciones ni siquiera son el peor problema, pero imagina que usaste un código similar en una página de inicio de sesión y un usuario ingresó ".*"como nombre de usuario.
Tobias
79

Tuve problemas con esto recientemente, uso este código y funciona bien para mí.

var data = 'Peter';

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

Uso directamente /Peter/itrabajo, pero uso '/'+data+'/i'y no trabajo para mí.

Donflopez
fuente
Bueno, lo intenté un poco más. Veo que también lo encuentro si solo escribo P ?? hmmm.
PeterBechP
Sí, lo uso para peticiones ajax para buscar usuarios. Puede modificar la RegExp.
Donflopez
36
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )
Kanomdook
fuente
@MikeShi ¿Cuál es un escenario de ejemplo de esto?
Len Joseph
@LenJoseph solo en general el ataque ReDoS: owasp.org/index.php/… , no sé si la mangosta es vulnerable en este punto, o si existe alguna funcionalidad para detectar entradas ReDoS y desinfectarlas a nivel de mangosta.
Mike Shi
14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})
Raynos
fuente
¿y si el valor es una var? ¿Cómo configurar eso? / varhere / i?
PeterBechP
2
@PeterBechP construye una expresión regular: \new RegExp(var, "i")
Raynos
funciona bien .. ahora tengo un problema .. solo tengo que encontrar a peter si la var es peter. Pero si configuro la var en 'p', todavía encontrará a Peter.
PeterBechP
@PeterBechP luego elimine la marca de insensibilidad a mayúsculas y minúsculas: \
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
fuente
13

Deberías usar una expresión regular para eso.

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

Sin embargo, tenga cuidado de que esta consulta no utilice index.

Sergio Tulentsev
fuente
9

doc mangosta para encontrar. mongodb doc para 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);
});

Tenga en cuenta que el primer argumento se pasa a mongoose.findOnela función: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"es el campo del documento que está buscando, "Ghost"es la expresión regular, "i"es para buscar coincidencias sin insensibles. Espero que esto te ayudará.

Shashith Darshana
fuente
¿Cuáles son las opciones de $?
kabuto178
8

La siguiente consulta encontrará los documentos con la cadena requerida sin distinción y con ocurrencia global también

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

Esto es lo que estoy usando.

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

Aquí mi código 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);
            });
         });
Enrico Giurin
fuente
1

si quiero consultar todos los registros en alguna condición, puedo usar esto:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);
disidente
fuente
Parece un uso innecesario de $regexcuando podría haberlo consumido { $exists: true }.
sean
0

Simplemente complementando la respuesta de @PeterBechP.

No olvides escapar de los caracteres especiales. 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
fuente
0

Esta es mi solución para convertir cada valor en un req.body en un parámetro LIKE de mangosta :

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 }) })
Salomón Bush
fuente