Like search in MongoDB

I have a site which allows users to search for a movie showtimes with a movie name. For example user can search for the "Green Hornet" or just a "Green" and he would receive a result of all "Green Hornet" movies.

My site is built with ME(A)N stack. MEAN stands for MongoDB, ExpressJS, AngularJS and NodeJS. A is put in parentheses because I'm not using Angular. So my stack should really be called a MEN!




MongoDB provides many ways to query data, but i chose to use regular expression search because its quite simple to do.

db.programs.find({'name': { $regex: 'Yeti', $options: 'i' } })

This is how you search for a movie called "Yeti" from a "programs" collection. Let's split that out and see what we have.

  • db.programs.find(); <= This is regular MongoDB find syntax. It queries the programs collection.
  • {'name' : ... <= This says that we are querying against "name" property (or column in sql world)
  • { $regex: 'Yeti', ... <= This defines that we are using regular expression search.
  • $options: 'i' ... <= And finally we are passing some options into regular expression search. "i" means that we are ignoring case.

So this query would return movies with names "Yeti", " Yeti " and "Yeti and his hairy sister" etc.

This works nicely until you are using special characters.

Like search with special characters




I have a movies in my database, which contains PG rating in their name. Like "The Unborn (K16) ". K16 means that its PG 16. If I query database with following query:

db.programs.find({'name': { $regex: 'The Unborn (K16)', $options: 'i' } })

It doesn't return any rows. It seems that special characters (parentheses) are causing problems. Lets try to escape them:

db.programs.find({'name': { $regex: 'The Unborn \(K16\)', $options: 'i' } })

Hey! Why in he.. this is not working? Maybe we don't have enough escape characters? They are free so let's spend a few more:

db.programs.find({'name': { $regex: 'The Unborn \\(K16\\)', $options: 'i' } })

Hallelujah! It's working. Now we have to find out what characters we need to escape, because there could be other ones.  Let's see what the mongodb guide says:

$regex uses “Perl Compatible Regular Expressions” (PCRE) as the matching engine.

That's cool. Let's Google a bit more and we find ourselves in stackoverflow which says:

For PCRE, and most other so-called Perl-compatible flavors, escape these outside character classes: .^$*+?()[{\|

Now we know what to escape. Let's start writing some Javascript.

JavaScript code to escape invalid characters


/* Add \\ before any invalid characters */
function escapeInvalidCharacters(myString) {
   /* Notice double \\ at the end */
   var escapedCharacters = [ ".","^","$","*","+","?","(",")","[","{","\\","|" ];
   var builtString = "";
   for(var i=0;i<myString.length;i++) {
       if(escapedCharacters.indexOf(myString[i]) > -1) {
           /* We found a invalid character. Add escape character before this invalid character */
           builtString = builtString + "\\" + myString[i];     
       } else {        
           builtString = builtString + myString[i];
       }
   }
   return builtString;
}

That's a nice little function to parse strings. Next we test it:

"The Unborn (K16) " is turned into "The Unborn \\(K16\\) "

Now add this code to the client side, because we want our clients to do all the hard work for us. This saves our server.

Code examples are free to use in any project. Commercial or non-commercial. 

3 comments:

  1. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a .Net developer learn from Dot Net Online Training from India. or learn thru ASP.NET Essential Training Online . Nowadays Dot Net has tons of job opportunities on various vertical industry.
    JavaScript Online Training from India

    ReplyDelete
  2. Thanks for sharing this blog post,Nice written skill core Java online training

    ReplyDelete