Ben
Ben

Reputation: 3357

Regex in mongoid search

I'm a little confused about how to achieve a regex with text searches in mongoid

I index with my contacts model like so:

index(FirstName: "text", LastName: "text")

In my search action I have:

search = '/.*' + search_string + '.*/'
@contacts.collection.find( { '$text': { '$search': search } }, "collation" => { "locale" => "en_US" } )

So when I pass a string, like "Joh" and I expect it to return case-insensitive results that will include contacts with names like "Majoh", "Majohboo" and "John" because of the regex I added around the search string.

What am I doing wrong and what should my query be like to achieve that? If I am unable to achieve that with a text type index, then what would you recommend I replace my indexing with?

Upvotes: 1

Views: 673

Answers (1)

D. SM
D. SM

Reputation: 14490

You seem to be confusing regular expression queries with full text search.

To perform a regular expression query, pass the regular expression:

irb(main):002:0> Band.create!(name: 'hello')
=> #<Band _id: 5e4b39e5026d7c7b6fcfc1ad, name: "hello", description: nil>
irb(main):003:0> Band.collection.find(name: /el/).first
=> {"_id"=>BSON::ObjectId('5e4b39e5026d7c7b6fcfc1ad'), "name"=>"hello"}
irb(main):004:0> Band.collection.find(name: /EL/).first
=> nil
irb(main):006:0> Band.collection.find(name: /EL/i).first
=> {"_id"=>BSON::ObjectId('5e4b39e5026d7c7b6fcfc1ad'), "name"=>"hello"}

This does not use $text operator.

To perform full text search, see https://docs.mongodb.com/mongoid/master/tutorials/mongoid-queries/#full-text-search. This does not use regular expressions.

You need to understand the difference between full text search and regular expression queries. Each has its uses. Developers are generally more familiar with regular expressions than with full text search, so perhaps you would benefit from reading up on how full text search works. Full text search does not work for arbitrary word fragments because it works on the basis of lexemes. Regular expressions do not reduce to word lexemes and thus are a poor choice for many natural language queries.

If you want to query with regular expressions, you can do that on multiple fields by combining multiple criteria (one per field) with $or. If you want full text search, regular expressions are not applicable, define a full text search index containing all of the fields you wish to search and use the $text operator.

Upvotes: 2

Related Questions