105

I like to to go find a user in mongoDb by looking for a user called value. The problem with:

username: 'peter'

is that i dont find it if the username is "Peter", or "PeTER".. or something like that.

So i want to do like sql

SELECT * FROM users WHERE username LIKE 'peter'

Hope you guys get what im askin for?

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

Neysor
  • 3,893
  • 11
  • 34
  • 66
techbech
  • 3,754
  • 5
  • 20
  • 28
  • 1
    Just an aside, the SQL query wouldn't find `Peter` or `PeTER` either as `LIKE` is not case-insensitive. – beny23 Mar 22 '12 at 14:54

15 Answers15

166

For those that were looking for a solution here it is:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});
Gabe
  • 5,643
  • 3
  • 26
  • 54
techbech
  • 3,754
  • 5
  • 20
  • 28
  • 2
    what does "i" argument mean? Does it have anything to do with case sensitivity? – AzaFromKaza Sep 19 '13 at 16:52
  • 4
    "i" is an argument for choosing a searching flag. "i" then is for case-insensitive. You can read more about it here. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions – techbech Sep 20 '13 at 17:07
  • 11
    This assumes the regex isn't invalid. If you add "[" as a username for example, will throw exception. Just ensure you are either try-catching or regexing your input prior and checking for [^a-zA-Z0-9] then not proceeding. In this case, its just test input so makes sense. – King Friday Jan 13 '14 at 00:43
  • 1
    $ = Match the end of the string – techbech Apr 29 '14 at 08:46
  • 1
    @JasonSebring Although I agree that input validation is not a bad idea, the best approach is an actual escaping algorithm. And exceptions are not even the worst problem, but imagine you used similar code on a login page and a user entered `".*"` as the username. – Tobias Oct 28 '14 at 09:59
  • @still_learning true. Do you know of one for this issue? I haven't thought much about it but it is necessary. – King Friday Oct 28 '14 at 13:11
  • @still_learning found it here -> http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex – King Friday Oct 28 '14 at 13:40
  • {[nameOFFieldHere]: new RegExp([charSetForFindHere], "i")} This is a little bit improved string literal handling with [ ] and in new RegExp ( ) , it automatically added /charSetForFindHere/ pattern with / and / , which comes from inbuilt regex eg: {"firstName": /Bri/} Therefore use above like : {[fieldnameVariable]: new RegExp([searchStringChars], "i")} with variable field name and variable char set. – Rakshitha Muranga Rodrigo Oct 19 '20 at 20:14
83

I had problems with this recently, i use this code and work fine for me.

var data = 'Peter';

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

Use directly /Peter/i work, but i use '/'+data+'/i' and not work for me.

Neysor
  • 3,893
  • 11
  • 34
  • 66
Donflopez
  • 1,178
  • 7
  • 13
42
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )
Sanchit Patiyal
  • 4,910
  • 1
  • 14
  • 31
Kanomdook
  • 715
  • 8
  • 6
  • @MikeShi What is an example scenario of this? – Len Joseph Jun 21 '19 at 14:36
  • @LenJoseph just in general the ReDoS attack: https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS, I'm unaware if mongoose is vulnerable at this point, or if there is any intended functionality to detect ReDoS inputs and sanitize them at the mongoose level. – Mike Shi Jun 23 '19 at 07:32
16
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})
Raynos
  • 166,823
  • 56
  • 351
  • 396
15
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
  • 1,390
  • 18
  • 23
13

You should use a regex for that.

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

Be wary, though, that this query doesn't use index.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
9

mongoose doc for find. mongodb doc for 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);
});

Note the first argument we pass to mongoose.findOne function: { "name" : { $regex: /Ghost/, $options: 'i' } }, "name" is the field of the document you are searching, "Ghost" is the regular expression, "i" is for case insensitive match. Hope this will help you.

Enrico Giurin
  • 2,183
  • 32
  • 30
Shashith Darshana
  • 2,715
  • 1
  • 25
  • 27
9

The following query will find the documents with required string case insensitively and with global occurrence also

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

This is what I'm using.

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

Here my code with 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
  • 2,183
  • 32
  • 30
2

Just complementing @PeterBechP 's answer.

Don't forget to scape the special chars. 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
  • 947
  • 1
  • 10
  • 23
2

For dynamic search, you can follow like this also,

const { keyword, skip, limit, sort } = pagination(params);
const search = keyword
      ? {
          title: {
            $regex: new RegExp(keyword, 'i')
          }
        }
      : {};

Model.find(search)
      .sort(sort)
      .skip(skip)
      .limit(limit);
Anil Loutombam
  • 355
  • 6
  • 19
1

if I want to query all record at some condition,I can use this:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);
maverick
  • 13
  • 4
  • Seems like an unnecessary use of `$regex` when you could have just used `{ $exists: true }`. – sean Jan 30 '20 at 06:06
1

This is my solution for converting every value in a req.body to a mongoose LIKE param:

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
  • 165
  • 9
0
var name = 'Peter';

model.findOne({
  name: {
    $regex: name,
    $options: 'i'
  }, 
  function(err, doc) {
  //your logic
});

for more information you can refer this link https://www.mongodb.com/docs/manual/reference/operator/query/regex/