Skip to content

Instantly share code, notes, and snippets.

@gautamrege
Created July 30, 2013 06:25
Show Gist options
  • Save gautamrege/6110733 to your computer and use it in GitHub Desktop.
Save gautamrege/6110733 to your computer and use it in GitHub Desktop.
Mongodb Text index search
class GeneralEntity
include Mongoid::Document
extend Moped::Search # to enable facetted text index search
field :org_name, type: String
# other fields
embeds_one :contact, as: :contactable
index({"contact.state" => 1, # filter with text index
"contact.first_name" => 'text',
"contact.last_name" => 'text',
"contact.middle_name" => 'text',
"org_name" => 'text',
"contact.email" => 'text'
},
{
weights: {
'org_name' => 10,
'contact.first_name' => 10,
'contact.last_name' => 10,
'contact.middle_name' => 5
},
name: 'ge_text_index'
}
)
# ...
end
module Moped
module Search
# @params
# str: Query string based on mongodb text search.
# http://docs.mongodb.org/manual/tutorial/search-for-text/
# options: limit, filter etc.
def search(str, options={})
options[:limit] = options[:limit] || 50 # default limit: 50 (mongoDB default: 100)
# Current result has a structure defined in http://docs.mongodb.org/manual/reference/text-search/
res = self.mongo_session.command({ text: self.collection.name, search: str}.merge(options))
# We shall now return the criteria fetched objects but as objects!!
self.where(:id.in => res['results'].collect {|o| o['obj']['_id']})
end
end
end
class GeneralEntitiesController < ApplicationController
before_filter :authenticate_user!
def search
org_name, first_name, middle_name, last_name, email = params[:general_entity][:org_name],
params[:general_entity][:contact_attributes][:first_name],
params[:general_entity][:contact_attributes][:middle_name],
params[:general_entity][:contact_attributes][:last_name],
params[:general_entity][:contact_attributes][:email]
state = params[:general_entity][:contact_attributes][:state] # mandatory
# Prepare search string for text index
str = [org_name, first_name, middle_name, last_name, email].join(' ')
# Filtered search
@general_entities = GeneralEntity.search(str, filter: { 'contact.state' => state} )
# Chain search criteria with specific facet search
@general_entities = @general_entities.where(:"contact.state" => state)
@general_entities = @general_entities.where(:name => /\b#{name}/i) unless name.blank?
@general_entities = @general_entities.where(:"contact.first_name" => /\b#{first_name}/i) unless first_name.blank?
@general_entities = @general_entities.where(:"contact.last_name" => /\b#{last_name}/i) unless last_name.blank?
@general_entities = @general_entities.where(:"contact.email" => /\b#{email}/i) unless email.blank?
@general_entities = @general_entities.where(:"contact.middle_name" => /\b#{middle_name}/i) unless middle_name.blank?
render json: @general_entities.to_json()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment