0

I'm using NodeJS with mongoose and my goal is to check if a pseudo requested by an user is not already in use. I want to let users choose pseudos with uppercase letters, but I don't want an user to choose "Foo" if "foo" is already in use.

I know I can use .find({pseudo: /foo/i}), but I need to inject a variable into the regular expression : new RegExp(pseudoToCheck, 'i')

At this point, I am stuck because the regular expression would fail if pseudoToCheck contains any special character used by regexps.

Should I use a function to escape 'pseudo' ? Is there a simpler way to do what I want ?

Thanks

(sorry for my English)

YannP
  • 1
  • 1
  • 1
    Yes, you need to escape your search string. See this post: http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript/3561711#3561711 – JohnnyHK Jul 05 '13 at 16:31

2 Answers2

3

I'm pretty sure there isn't an easier way to do what you need without first escaping "magic" RegExp characters using a function like:

function escapeRegExpChars(text) {
    return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}

So, assuming you are searching for the user handle (pseudo) "$Foo(.)Bar+", you would:

var query = new RegExp(escapeRegExpChars(handle),'i')

which produces:

/\$Foo\(\.\)Bar\+/i 

But there are drawbacks to using a RegExp to search for records in a database, the most onerous being that the RegExp must be applied to each record individually. This is called a "full scan" of the table and is very inefficient.

To improve performance considerably (by removing the requirement for a full table scan), I'd keep two copies of the handle in your database, one for display purposes and the other to ease search.

To create the search oriented handle, you could:

function createEscapedHandle(handle){
    return handle.toLowerCase().replace(/(\W)/g,function(ch){
        return '%' + ch.charCodeAt(0).toString(16);
    });
}

var handle = '$Foo(.)Bar+',
             escapedHandle = createEscapedHandle(handle);

// where escaped handle is '%24foo%28%2e%29bar%2b'

Save both the original handle and its escaped version in your db, and search on the escaped version.

I believe you'll find that this trade-off between processing (matching the RegExp against every record) vs. the extra storage space required to save the escaped version of the handle will provide you significantly faster results.

Rob Raisch
  • 17,040
  • 4
  • 48
  • 58
0

Case insensitive search with symbols. MongoDB console:

db.keywordsdocs.find({keyword:{ $regex:new RegExp('^' + 'string with symbols and different cases'.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')}});

Mongoose:

keywordsdocs.find({keyword:{$regex: new RegExp('^' + "string with symbols and different cases".replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')}},function(err, key) { console.log(key)});
Arjun G
  • 2,194
  • 1
  • 18
  • 19