Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mongoid/mongoid_search
Simple full text search for Mongoid ORM
https://github.com/mongoid/mongoid_search
Last synced: 17 days ago
JSON representation
Simple full text search for Mongoid ORM
- Host: GitHub
- URL: https://github.com/mongoid/mongoid_search
- Owner: mongoid
- License: mit
- Created: 2010-09-16T22:49:56.000Z (about 14 years ago)
- Default Branch: master
- Last Pushed: 2024-02-15T18:43:27.000Z (9 months ago)
- Last Synced: 2024-06-17T05:27:49.259Z (5 months ago)
- Language: Ruby
- Homepage:
- Size: 180 KB
- Stars: 319
- Watchers: 17
- Forks: 113
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
- awesome-ruby - Mongoid Search - Simple full text search implementation for Mongoid. (Search)
README
# Mongoid Search
Mongoid Search is a simple full text search implementation for Mongoid ORM. It supports Mongoid 3, 4, 5 and 6 and performs well for small data sets. If your searchable model is big (i.e. 1.000.000+ records), [mongoid_fulltext](https://github.com/mongoid/mongoid_fulltext), ElasticSearch, Solr or Sphinx may suit you better.
[![Build Status](https://travis-ci.org/mongoid/mongoid_search.svg?branch=master)](https://travis-ci.org/mongoid/mongoid_search)
## Installation
In your Gemfile:
```ruby
gem 'mongoid_search'
```Then:
```
bundle install
```## Examples
```ruby
class Product
include Mongoid::Document
include Mongoid::Search
field :brand
field :name
field :unit
field :info, type: Hashhas_many :tags
belongs_to :categorysearch_in :brand, :name, tags: :name, category: :name, info: %i[summary description]
search_in :unit, index: :_unit_keywords
endclass Tag
include Mongoid::Document
field :namebelongs_to :product
endclass Category
include Mongoid::Document
field :namehas_many :products
end
```Now when you save a product, you get a `_keywords` field automatically:
```ruby
p = Product.new brand: 'Apple', name: 'iPhone', unit: 'kilogram', info: { summary: 'Info-summary', description: 'Info-description' }
p.tags << Tag.new(name: 'Amazing')
p.tags << Tag.new(name: 'Awesome')
p.tags << Tag.new(name: 'Superb')
p.save
# => true
p._keywords
# => ["amazing", "apple", "awesome", "iphone", "superb", "Info-summary", "Info-description"]
p._unit_keywords
# => ["kilogram"]
```Now you can run search, which will look in the `_keywords` field and return all matching results:
```ruby
Product.full_text_search("apple iphone").size
# => 1
```You can also search in "virtual" fields by defining them as methods. This can be useful when you have a method with dynamic fields (i.e. variable schema).
```ruby
class ModelWithDynamicFields
...
search_in :search_datadef search_data
# concatenate all String fields' values
self.attributes.select{|k,v| v.is_a?(String) }.values.join(' ')
end
end
```
Mongoid_search will run the method before save and use it's output to populate the `_keywords` field.Of course, some models could have more than one index. For instance, two different searches with different fields, so you could even specify from which index should be searched:
```ruby
Product.full_text_search("kilogram", index: :_unit_keywords).size
# => 1
```Note that the search is case insensitive, and accept partial searching too:
```ruby
Product.full_text_search('ipho').size
# => 1
```Assuming you have a category with multiple products you can use the following code to search for 'iphone' in products cheaper than $499.
```ruby
category.products.where(:price.lt => 499).full_text_search('iphone').asc(:price)
```To index or reindex all existing records, run this rake task
```
$ rake mongoid_search:index
```## Options
### match
* `:any` - match any occurrence
* `:all` - match all occurrencesDefault is `:any`.
```ruby
Product.full_text_search('apple motorola', match: :any).size
# => 1Product.full_text_search('apple motorola', match: :all).size
# => 0
```### allow\_empty\_search
* `true` - will return `Model.all`
* `false` - will return `[]`Default is `false`.
```ruby
Product.full_text_search('', allow_empty_search: true).size
# => 1
```### relevant_search
* `true` - adds relevance information to the results
* `false` - no relevance informationDefault is `false`.
```ruby
Product.full_text_search('amazing apple', relevant_search: true)
# => [#]
```Please note that relevant_search will return an Array and not a Criteria object. The search method should always be called in the end of the method chain.
### index
Default is `_keywords`.
```ruby
Product.full_text_search('amazing apple', index: :_keywords)
# => [#]Product.full_text_search('kg', index: :_unit_keywords)
# => [#]
```index enables to have two or more different searches, with different or same fields. It should be noted that indexes are exclusive per each one.
## Initializer
Alternatively, you can create an initializer to setup those options:
```ruby
Mongoid::Search.setup do |config|
## Default matching type. Match :any or :all searched keywords
config.match = :any## If true, an empty search will return all objects
config.allow_empty_search = false## If true, will search with relevance information
config.relevant_search = false## Stem keywords
config.stem_keywords = false## Add a custom proc returning strings to replace the default stemmer
# For example using ruby-stemmer:
# config.stem_proc = Proc.new { |word| Lingua.stemmer(word, :language => 'nl') }## Words to ignore
config.ignore_list = []## An array of words
# config.ignore_list = %w{ a an to from as }## Or from a file
# config.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]## Search using regex (slower)
config.regex_search = true## Regex to search
## Match partial words on both sides (slower)
config.regex = Proc.new { |query| /#{query}/ }## Match partial words on the beginning or in the end (slightly faster)
# config.regex = Proc.new { |query| /^#{query}/ }
# config.regex = Proc.new { |query| /#{query}$/ }# Ligatures to be replaced
# http://en.wikipedia.org/wiki/Typographic_ligature
config.ligatures = { "œ"=>"oe", "æ"=>"ae" }# Strip symbols regex to be replaced. These symbols will be replaced by space
config.strip_symbols = /[._:;'\"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/# Strip accents regex to be replaced. These sybols will be removed after strip_symbols replacing
config.strip_accents = /[^\s\p{Alnum}]/# Minimum word size. Words smaller than it won't be indexed
config.minimum_word_size = 2
end
```