Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for ILIKE search feature #509

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ end
* [`:trigram` (Trigram search)](#trigram-trigram-search)
* [`:threshold`](#threshold)
* [`:word_similarity`](#word_similarity)
* [`:ilike` (Basic Search)](#ilike-basic-search)
* [Limiting Fields When Combining Features](#limiting-fields-when-combining-features)
* [Ignoring accent marks](#ignoring-accent-marks)
* [Using tsvector columns](#using-tsvector-columns)
Expand Down Expand Up @@ -548,7 +549,7 @@ search techniques.
```ruby
class Beer < ActiveRecord::Base
include PgSearch::Model
pg_search_scope :search_name, against: :name, using: [:tsearch, :trigram, :dmetaphone]
pg_search_scope :search_name, against: :name, using: [:tsearch, :trigram, :dmetaphone, :ilike]
end
```

Expand All @@ -562,7 +563,8 @@ class Beer < ActiveRecord::Base
using: {
:trigram => {},
:dmetaphone => {},
:tsearch => { :prefix => true }
:tsearch => { :prefix => true },
:ilike => {}
}
end
```
Expand All @@ -573,6 +575,7 @@ The currently implemented features are
* :trigram - [Trigram search](http://www.postgresql.org/docs/current/static/pgtrgm.html), which
requires the trigram extension
* :dmetaphone - [Double Metaphone search](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html#AEN177521), which requires the fuzzystrmatch extension
* :ilike - Basic search using built in ilike operator


#### :tsearch (Full Text Search)
Expand Down Expand Up @@ -976,6 +979,22 @@ Sentence.similarity_like("word") # => []
Sentence.word_similarity_like("word") # => [sentence]
```

### :ilike (Basic Search)

Basic search using ilike. This will look for anything containing an exact match, ie `%QUERY%`. This is useful in situations where you are looking for a substring.

```ruby
class Company < ActiveRecord::Base
include PgSearch::Model
pg_search_scope :find_substring,
against: :name,
using: :ilike
end

macrohard = Company.create! name: "MacroHard"
Website.find_substring("hard") # => [macrohard]
```

### Limiting Fields When Combining Features

Sometimes when doing queries combining different features you
Expand Down
1 change: 1 addition & 0 deletions lib/pg_search/features.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require "pg_search/features/feature"

require "pg_search/features/dmetaphone"
require "pg_search/features/ilike"
require "pg_search/features/trigram"
require "pg_search/features/tsearch"

Expand Down
29 changes: 29 additions & 0 deletions lib/pg_search/features/ilike.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module PgSearch
module Features
class ILike < Feature
def conditions
Arel::Nodes::Grouping.new(
Arel::Nodes::InfixOperation.new(
"ILIKE",
normalized_document,
normalized_query
)
)
end

def rank
Arel::Nodes::Grouping.new(Arel.sql("0")) # no ranking or delegate to tsearch like DMetaphone?
end

private

def normalized_query
Arel.sql(connection.quote("%#{query}%"))
end

def normalized_document
Arel::Nodes::Grouping.new(Arel.sql(document))
end
end
end
end
1 change: 1 addition & 0 deletions lib/pg_search/scope_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def subquery_join

FEATURE_CLASSES = {
dmetaphone: Features::DMetaphone,
ilike: Features::ILike,
tsearch: Features::TSearch,
trigram: Features::Trigram
}.freeze
Expand Down
48 changes: 48 additions & 0 deletions spec/lib/pg_search/features/i_like_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require "spec_helper"
require "ostruct"

# rubocop:disable RSpec/MultipleMemoizedHelpers
describe PgSearch::Features::ILike do
subject(:feature) { described_class.new(query, options, columns, Model, normalizer) }

let(:query) { "lolwut" }
let(:options) { {} }
let(:columns) {
[
PgSearch::Configuration::Column.new(:name, nil, Model),
PgSearch::Configuration::Column.new(:content, nil, Model)
]
}
let(:normalizer) { PgSearch::Normalizer.new(config) }
let(:config) { OpenStruct.new(ignore: []) }

let(:coalesced_columns) do
<<~SQL.squish
coalesce(#{Model.quoted_table_name}."name"::text, '')
|| ' '
|| coalesce(#{Model.quoted_table_name}."content"::text, '')
SQL
end

with_model :Model do
table do |t|
t.string :name
t.string :content
end
end

describe "conditions" do
it "escapes the search document and query" do
expect(feature.conditions.to_sql).to eq("((#{coalesced_columns}) ILIKE '%#{query}%')")
end
end

describe "#rank" do
it "doesn't do different ranks" do
expect(feature.rank.to_sql).to eq("(0)")
end
end
end
# rubocop:enable RSpec/MultipleMemoizedHelpers