-
-
Save julianalucena/34246b0c837fd163cc0f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module TextSearch | |
class BaseSearch | |
def initialize | |
@filters = {} | |
@page = 1 | |
@per_page = Search::Application.config.results_count | |
@term = nil | |
end | |
class << self | |
def search(term = nil) | |
new.search(term) | |
end | |
end | |
def search(term = nil) | |
raise NotImplementedError, 'You must implement #search' | |
end | |
def page(number) | |
@page = number.to_i if number | |
self | |
end | |
def per_page(qty) | |
@per_page = qty.to_i if qty | |
self | |
end | |
def order(ordering) | |
return self if ordering.blank? | |
attribute, order = ordering.split(' ') | |
@search.sort { by attribute, order.downcase } | |
self | |
end | |
def results | |
@search.filter :and, @filters.values unless @filters.empty? | |
@search.size(@per_page) | |
@search.from(from_page) | |
@search.results | |
end | |
private | |
attr_reader :filters | |
def from_page | |
(@page - 1) * @per_page | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module TextSearch | |
class BookSearch < BaseSearch | |
def search(term, country: 'BR', **options) | |
@search = Tire.search(search_indexes) do |s| | |
s.query do | |
boolean do | |
should { match :description, term, operator: "AND", boost: 5 } | |
should { match :'description.partial', term, operator: 'AND', boost: 4 } | |
should { match :'description.partial_middle', term, operator: 'AND', boost: 2 } | |
should { match :'description.partial_back', term, operator: 'AND', boost: 4 } | |
end | |
end | |
end | |
Filters::InactiveFilter.apply!(filters, false) | |
Filters::CountryFilter.apply!(filters, country) | |
self | |
end | |
def filter(conditions) | |
Filters::PriceFilter.apply!(filters, conditions) | |
Filters::CategoryFilter.apply!(filters, conditions) | |
Filters::PublisherFilter.apply!(filters, conditions) | |
self | |
end | |
def with_facets | |
Facets::PriceStatisticsFacet.apply!(@search, filters) | |
Facets::CategoryFacet.apply!(@search, filters) | |
Facets::PublisherFacet.apply!(@search, filters) | |
self | |
end | |
private | |
def search_indexes | |
[Book.index_name] | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe TextSearch::BookSearch do | |
describe "#search", elasticsearch: true do | |
it "return self" do | |
expect(subject.search('term')).to eq(subject) | |
end | |
context do | |
let!(:book) { FactoryGirl.create(:book) } | |
before { refresh_index_for Book } | |
after { reset_index_for Book} | |
it "matches with book's name" do | |
results = subject.search(book.name).results | |
expect(results).to have(1).item | |
expect(results.first.name).to eq(book.name) | |
end | |
context do | |
let(:book) { FactoryGirl.create(:book, name: 'lorem ipsumm dorem') } | |
it "matches with book's beggining partial name" do | |
results = subject.search('lorem').results | |
expect(results).to have(1).item | |
expect(results.first.name).to eq(book.name) | |
end | |
it "matches with book's ending partial name" do | |
results = subject.search('dorem').results | |
expect(results).to have(1).item | |
expect(results.first.name).to eq(book.name) | |
end | |
it "matches with book's middle partial name" do | |
results = subject.search('ipsumm').results | |
expect(results).to have(1).item | |
expect(results.first.name).to eq(book.name) | |
end | |
end | |
end | |
describe "default filters" do | |
describe "inactive filter" do | |
it "applies InactiveFilter with flag: true" do | |
expect(TextSearch::Filters::ActiveFilter).to receive(:apply!). | |
with(an_instance_of(Hash), true) | |
subject.search('term') | |
end | |
end | |
describe 'country filter' do | |
let(:country) { 'Country' } | |
it "applies CountryFilter with passed country" do | |
expect(TextSearch::Filters::CountryFilter).to receive(:apply!). | |
with(an_instance_of(Hash), country) | |
subject.search('term', country: country) | |
end | |
end | |
end | |
end | |
describe "#filter", elasticsearch: true do | |
let(:conditions) { double(Hash, :[] => nil) } | |
describe "price filter" do | |
it "applies PriceFilter with passed conditions" do | |
expect(TextSearch::Filters::PriceFilter).to receive(:apply!). | |
with(an_instance_of(Hash), conditions) | |
subject.search('term').filter(conditions) | |
end | |
end | |
describe "category filter" do | |
it "applies CategoryFilter with passed conditions" do | |
expect(TextSearch::Filters::CategoryFilter).to receive(:apply!). | |
with(an_instance_of(Hash), conditions) | |
subject.search('term').filter(conditions) | |
end | |
end | |
describe 'publisher filter' do | |
it "applies PublisherFilter with passed conditions" do | |
expect(TextSearch::Filters::PublisherFilter).to receive(:apply!). | |
with(an_instance_of(Hash), conditions) | |
subject.search('term').filter(conditions) | |
end | |
end | |
end | |
describe '#with_facets', elasticsearch: true do | |
describe "publisher facet" do | |
it "applies PublisherFacet" do | |
expect(TextSearch::Facets::PublisherFacet).to receive(:apply!) | |
subject.search('term').with_facets | |
end | |
end | |
describe "price_statistics facet" do | |
it "applies PriceStatisticsFacet" do | |
expect(TextSearch::Facets::PriceStatisticsFacet).to receive(:apply!) | |
subject.search('term').with_facets | |
end | |
end | |
describe 'category facet' do | |
it "applies CategoryFacet" do | |
expect(TextSearch::Facets::CategoryFacet).to receive(:apply!) | |
subject.search('term').with_facets | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module TextSearch | |
module Facets | |
class CategoryFacet | |
class << self | |
def apply!(*args) | |
new(*args).apply! | |
end | |
end | |
def initialize(search, filters) | |
@search = search | |
@filters = filters | |
end | |
def apply! | |
facet_filters = filters.except(:categories_ids) | |
search.facet :category_id do | |
terms :categories_ids, size: 100, all_terms: false | |
unless facet_filters.empty? | |
facet_filter :and, facet_filters.values | |
end | |
end | |
end | |
private | |
attr_reader :search, :filters | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe TextSearch::Facets::CategoryFacet, elasticsearch: true do | |
include TextSearchHelpers | |
subject do | |
text_search_for(Book).add_facets do |search, filters| | |
described_class.apply!(search, filters) | |
end | |
end | |
after { reset_index_for Book } | |
let(:facets) { subject.with_facets.results.facets } | |
let(:facet) { facets['category_id'] } | |
let!(:book) { FactoryGirl.create(:book, category: category) } | |
let(:category) { FactoryGirl.create(:category) } | |
before { refresh_index_for Book } | |
it "has category_id facet" do | |
expect(facets).to have_key('category_id') | |
end | |
it "has qty of books per category" do | |
expect(facet['terms']).to have(2).items | |
categories_ids = facet['terms'].map { |f| f['term'] } | |
expect(categories_ids).to match_array([category.id]) | |
quantities = facet['terms'].map { |f| f['count'] } | |
expect(quantities).to match_array([1]) | |
end | |
context "when there are filters applied to the search" do | |
let(:facets) { subject.filter(id: book.id).with_facets.results.facets } | |
it "applies the filters to the facet" do | |
FactoryGirl.create(:book) | |
refresh_index_for Book | |
subject.add_filters do |filters, conditions| | |
filters[:id] = { term: conditions } | |
end | |
expect(facet['terms']).to have(2).items | |
end | |
it "does not apply category filter to the facet" do | |
subject.add_filters do |filters, _| | |
filters[:categories_ids] = { term: { categories_ids: category.id } } | |
end | |
expect(facet['terms']).to have(2).items | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module TextSearch | |
module Filters | |
class CategoryFilter | |
class << self | |
def apply!(*args) | |
new(*args).apply! | |
end | |
end | |
def initialize(filters, conditions) | |
@filters = filters | |
@category_id = conditions[:category_id] | |
end | |
def apply! | |
return if category_id.blank? | |
filters[:categories_ids] = { | |
term: { categories_ids: category_id } | |
} | |
end | |
private | |
attr_reader :category_id | |
attr_accessor :filters | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe TextSearch::Filters::CategoryFilter, elasticsearch: true do | |
include TextSearchHelpers | |
subject do | |
text_search_for(Book).add_filters do |filters, conditions| | |
described_class.apply!(filters, conditions) | |
end | |
end | |
after { reset_index_for Book } | |
let(:category) { FactoryGirl.create(:category) } | |
let!(:book) { FactoryGirl.create(:book, category: category) } | |
before do | |
FactoryGirl.create(:book) | |
refresh_index_for Book | |
end | |
it "returns books that belongs to specified category" do | |
results = subject.filter(category_id: category.id).results | |
expect(results.count).to eq(1) | |
expect(results.first.id).to eq(book.id.to_s) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment