Commit aaa5d1b8fec04f9401bb3fff7459c3f253fdc908
1 parent
65882f09
Exists in
elasticsearch_sort
Refactored elasticsearch_plugin and elasticsearch_api
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
Showing
11 changed files
with
261 additions
and
60 deletions
Show diff stats
plugins/elasticsearch/helpers/elasticsearch_helper.rb
@@ -19,42 +19,16 @@ module ElasticsearchHelper | @@ -19,42 +19,16 @@ module ElasticsearchHelper | ||
19 | } | 19 | } |
20 | end | 20 | end |
21 | 21 | ||
22 | - def fields_from_models klasses | ||
23 | - fields = Set.new | ||
24 | - klasses.each do |klass| | ||
25 | - klass::SEARCHABLE_FIELDS.map do |key, value| | ||
26 | - if value and value[:weight] | ||
27 | - fields.add "#{key}^#{value[:weight]}" | ||
28 | - else | ||
29 | - fields.add "#{key}" | ||
30 | - end | ||
31 | - end | ||
32 | - end | ||
33 | - fields.to_a | ||
34 | - end | ||
35 | - | ||
36 | - def get_sort_by sort_by | ||
37 | - case sort_by | ||
38 | - when "lexical" | ||
39 | - { "name.raw" => {"order" => "asc" }} | ||
40 | - when "recent" | ||
41 | - { "created_at" => {"order" => "desc"}} | ||
42 | - end | ||
43 | - end | ||
44 | - | ||
45 | def process_results | 22 | def process_results |
46 | - selected_type = (params[:selected_type]|| :all).to_sym | ||
47 | - if selected_type == :all | ||
48 | - search_from_all_models | ||
49 | - else | ||
50 | - search_from_model selected_type | ||
51 | - end | 23 | + selected_type = (params[:selected_type].presence|| :all).to_sym |
24 | + selected_type == :all ? search_from_all_models : search_from_model(selected_type) | ||
52 | end | 25 | end |
53 | 26 | ||
27 | + private | ||
28 | + | ||
54 | def search_from_all_models | 29 | def search_from_all_models |
55 | query = get_query params[:query], sort_by: get_sort_by(params[:selected_filter]) | 30 | query = get_query params[:query], sort_by: get_sort_by(params[:selected_filter]) |
56 | - models = searchable_models | ||
57 | - Elasticsearch::Model.search(query, models, size: default_per_page(params[:per_page])).page(params[:page]).records | 31 | + Elasticsearch::Model.search(query,searchable_models, size: default_per_page(params[:per_page])).page(params[:page]).records |
58 | end | 32 | end |
59 | 33 | ||
60 | def search_from_model model | 34 | def search_from_model model |
@@ -68,17 +42,28 @@ module ElasticsearchHelper | @@ -68,17 +42,28 @@ module ElasticsearchHelper | ||
68 | end | 42 | end |
69 | end | 43 | end |
70 | 44 | ||
71 | - def default_per_page per_page | 45 | + def default_per_page per_page=nil |
72 | per_page ||= 10 | 46 | per_page ||= 10 |
73 | end | 47 | end |
74 | 48 | ||
75 | - private | 49 | + def get_sort_by sort_by |
50 | + case sort_by | ||
51 | + when "lexical" | ||
52 | + { "name.raw" => {"order" => "asc" }} | ||
53 | + when "recent" | ||
54 | + { "created_at" => {"order" => "desc"}} | ||
55 | + end | ||
56 | + end | ||
76 | 57 | ||
77 | def searchable_models | 58 | def searchable_models |
78 | - ElasticsearchHelper::searchable_types.except(:all).keys.map { | model | model.to_s.classify.constantize } | 59 | + begin |
60 | + ElasticsearchHelper::searchable_types.except(:all).keys.map { | model | model.to_s.classify.constantize } | ||
61 | + rescue | ||
62 | + [] | ||
63 | + end | ||
79 | end | 64 | end |
80 | 65 | ||
81 | - def query_method expression, fields | 66 | + def query_method expression="", fields=[] |
82 | query_exp = {} | 67 | query_exp = {} |
83 | if expression.blank? | 68 | if expression.blank? |
84 | query_exp = { | 69 | query_exp = { |
@@ -107,8 +92,21 @@ module ElasticsearchHelper | @@ -107,8 +92,21 @@ module ElasticsearchHelper | ||
107 | } | 92 | } |
108 | 93 | ||
109 | query[:sort] = [sort_by,"_score"] if sort_by | 94 | query[:sort] = [sort_by,"_score"] if sort_by |
110 | - | ||
111 | query | 95 | query |
112 | end | 96 | end |
113 | 97 | ||
98 | + def fields_from_models klasses | ||
99 | + fields = Set.new | ||
100 | + klasses.each do |klass| | ||
101 | + klass::SEARCHABLE_FIELDS.map do |key, value| | ||
102 | + if value and value[:weight] | ||
103 | + fields.add "#{key}^#{value[:weight]}" | ||
104 | + else | ||
105 | + fields.add "#{key}" | ||
106 | + end | ||
107 | + end | ||
108 | + end | ||
109 | + fields.to_a | ||
110 | + end | ||
111 | + | ||
114 | end | 112 | end |
plugins/elasticsearch/lib/elasticsearch_plugin/entities.rb
1 | module Elasticsearch | 1 | module Elasticsearch |
2 | module Entities | 2 | module Entities |
3 | + | ||
3 | class Result < Api::Entity | 4 | class Result < Api::Entity |
4 | root "results","result" | 5 | root "results","result" |
5 | 6 | ||
@@ -7,11 +8,24 @@ module Elasticsearch | @@ -7,11 +8,24 @@ module Elasticsearch | ||
7 | options[:types].detect { |type| type.to_s.upcase if object.is_a? (type.to_s.classify.constantize) } | 8 | options[:types].detect { |type| type.to_s.upcase if object.is_a? (type.to_s.classify.constantize) } |
8 | end | 9 | end |
9 | 10 | ||
11 | + expose :id | ||
10 | expose :name | 12 | expose :name |
11 | 13 | ||
12 | expose :author, if: lambda { |object,options| object.respond_to? 'author'} do |object, options| | 14 | expose :author, if: lambda { |object,options| object.respond_to? 'author'} do |object, options| |
13 | object.author.present? ? object.author.name : "" | 15 | object.author.present? ? object.author.name : "" |
14 | end | 16 | end |
17 | + | ||
18 | + expose :description, if: lambda { |object,options| object.respond_to? 'description'} do |object, options| | ||
19 | + object.description.present? ? object.description : "" | ||
20 | + end | ||
21 | + | ||
22 | + expose :abstract, if: lambda { |object,options| object.respond_to? 'abstract'} do |object, options| | ||
23 | + object.abstract.present? ? object.abstract : "" | ||
24 | + end | ||
25 | + | ||
26 | + expose :created_at, :format_with => :timestamp | ||
27 | + expose :updated_at, :format_with => :timestamp | ||
15 | end | 28 | end |
29 | + | ||
16 | end | 30 | end |
17 | end | 31 | end |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_api_test.rb
@@ -10,7 +10,7 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | @@ -10,7 +10,7 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | ||
10 | 10 | ||
11 | def create_instances | 11 | def create_instances |
12 | 7.times.each {|index| create_user "person #{index}"} | 12 | 7.times.each {|index| create_user "person #{index}"} |
13 | - 4.times.each {|index| fast_create Community, name: "community #{index}", created_at: Date.new } | 13 | + 4.times.each {|index| fast_create Community, name: "community #{index}" } |
14 | end | 14 | end |
15 | 15 | ||
16 | should 'show all types avaliable in /search/types endpoint' do | 16 | should 'show all types avaliable in /search/types endpoint' do |
@@ -47,5 +47,4 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | @@ -47,5 +47,4 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | ||
47 | assert_equal 200, last_response.status | 47 | assert_equal 200, last_response.status |
48 | assert_equal 4, json["results"].count | 48 | assert_equal 4, json["results"].count |
49 | end | 49 | end |
50 | - | ||
51 | end | 50 | end |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_entities_test.rb
0 → 100644
@@ -0,0 +1,122 @@ | @@ -0,0 +1,122 @@ | ||
1 | +require "#{File.dirname(__FILE__)}/../../test_helper" | ||
2 | + | ||
3 | +class ElasticsearchPluginEntitiesTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + include ElasticsearchTestHelper | ||
6 | + | ||
7 | + def indexed_models | ||
8 | + [Person,TextArticle,UploadedFile,Community,Event] | ||
9 | + end | ||
10 | + | ||
11 | + def create_instances | ||
12 | + user = create_user "sample person" | ||
13 | + | ||
14 | + fast_create Community, name: "sample community", created_at: 10.days.ago,updated_at: 5.days.ago | ||
15 | + fast_create UploadedFile, name: "sample uploadedfile", created_at: 3.days.ago, updated_at: 1.days.ago, author_id: user.person.id, abstract: "sample abstract" | ||
16 | + fast_create Event, name: "sample event", created_at: 20.days.ago, updated_at: 5.days.ago, author_id: user.person.id, abstract: "sample abstract" | ||
17 | + | ||
18 | + fast_create RawHTMLArticle, name: "sample raw html article", created_at: 15.days.ago ,updated_at: 5.days.ago, author_id: user.person.id | ||
19 | + fast_create TinyMceArticle, name: "sample tiny mce article", created_at: 5.days.ago, updated_at: 5.days.ago, author_id: user.person.id | ||
20 | + end | ||
21 | + | ||
22 | + should 'show attributes from person' do | ||
23 | + params = {:selected_type => "person" } | ||
24 | + get "/api/v1/search?#{params.to_query}" | ||
25 | + json= JSON.parse(last_response.body) | ||
26 | + | ||
27 | + expected_person = Person.find_by name: "sample person" | ||
28 | + | ||
29 | + assert_equal 200, last_response.status | ||
30 | + assert_equal expected_person.id, json['results'][0]['id'] | ||
31 | + assert_equal expected_person.name, json['results'][0]['name'] | ||
32 | + assert_equal expected_person.type, json['results'][0]['type'] | ||
33 | + assert_equal "", json['results'][0]['description'] | ||
34 | + assert_equal expected_person.created_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][0]['created_at'] | ||
35 | + assert_equal expected_person.updated_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][0]['updated_at'] | ||
36 | + end | ||
37 | + | ||
38 | + should 'show attributes from community' do | ||
39 | + params = {:selected_type => "community" } | ||
40 | + get "/api/v1/search?#{params.to_query}" | ||
41 | + json= JSON.parse(last_response.body) | ||
42 | + | ||
43 | + expected_community = Community.find_by name: "sample community" | ||
44 | + | ||
45 | + assert_equal 200, last_response.status | ||
46 | + assert_equal expected_community.id, json['results'][0]['id'] | ||
47 | + assert_equal expected_community.name, json['results'][0]['name'] | ||
48 | + assert_equal expected_community.type, json['results'][0]['type'] | ||
49 | + assert_equal "", json['results'][0]['description'] | ||
50 | + assert_equal expected_community.created_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][0]['created_at'] | ||
51 | + assert_equal expected_community.updated_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][0]['updated_at'] | ||
52 | + end | ||
53 | + | ||
54 | + should 'show attributes from text_article' do | ||
55 | + params = {:selected_type => "text_article" } | ||
56 | + get "/api/v1/search?#{params.to_query}" | ||
57 | + | ||
58 | + json= JSON.parse(last_response.body) | ||
59 | + | ||
60 | + assert_equal 200, last_response.status | ||
61 | + | ||
62 | + expected_text_articles = TextArticle.all | ||
63 | + | ||
64 | + expected_text_articles.each_with_index {|object,index| | ||
65 | + assert_equal object.id, json['results'][index]['id'] | ||
66 | + assert_equal object.name, json['results'][index]['name'] | ||
67 | + assert_equal "TextArticle", json['results'][index]['type'] | ||
68 | + | ||
69 | + expected_author = (object.author.nil?) ? "" : object.author.name | ||
70 | + | ||
71 | + assert_equal expected_author, json['results'][index]['author'] | ||
72 | + assert_equal object.created_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['created_at'] | ||
73 | + assert_equal object.updated_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['updated_at'] | ||
74 | + } | ||
75 | + end | ||
76 | + | ||
77 | + should 'show attributes from uploaded_file' do | ||
78 | + params = {:selected_type => "uploaded_file"} | ||
79 | + get "/api/v1/search?#{params.to_query}" | ||
80 | + | ||
81 | + json= JSON.parse(last_response.body) | ||
82 | + | ||
83 | + assert_equal 200, last_response.status | ||
84 | + | ||
85 | + expected_uploaded_files = UploadedFile.all | ||
86 | + expected_uploaded_files.each_with_index {|object,index| | ||
87 | + assert_equal object.id, json['results'][index]['id'] | ||
88 | + assert_equal object.name, json['results'][index]['name'] | ||
89 | + assert_equal object.abstract, json['results'][index]['abstract'] | ||
90 | + assert_equal "UploadedFile", json['results'][index]['type'] | ||
91 | + | ||
92 | + expected_author = (object.author.nil?) ? "" : object.author.name | ||
93 | + assert_equal expected_author, json['results'][index]['author'] | ||
94 | + | ||
95 | + assert_equal object.created_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['created_at'] | ||
96 | + assert_equal object.updated_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['updated_at'] | ||
97 | + } | ||
98 | + end | ||
99 | + | ||
100 | + should 'show attributes from event' do | ||
101 | + params = {:selected_type => "event"} | ||
102 | + get "/api/v1/search?#{params.to_query}" | ||
103 | + | ||
104 | + json= JSON.parse(last_response.body) | ||
105 | + | ||
106 | + assert_equal 200, last_response.status | ||
107 | + expected_events = Event.all | ||
108 | + expected_events.each_with_index {|object,index| | ||
109 | + assert_equal object.id, json['results'][index]['id'] | ||
110 | + assert_equal object.name, json['results'][index]['name'] | ||
111 | + assert_equal object.abstract, json['results'][index]['abstract'] | ||
112 | + assert_equal "Event", json['results'][index]['type'] | ||
113 | + | ||
114 | + expected_author = (object.author.nil?) ? "" : object.author.name | ||
115 | + assert_equal expected_author, json['results'][index]['author'] | ||
116 | + | ||
117 | + assert_equal object.created_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['created_at'] | ||
118 | + assert_equal object.updated_at.strftime("%Y/%m/%d %H:%M:%S"), json['results'][index]['updated_at'] | ||
119 | + } | ||
120 | + end | ||
121 | + | ||
122 | +end |
plugins/elasticsearch/test/unit/helpers/elasticsearch_helper_test.rb
0 → 100644
@@ -0,0 +1,90 @@ | @@ -0,0 +1,90 @@ | ||
1 | +require "#{File.dirname(__FILE__)}/../../test_helper" | ||
2 | +require_relative '../../../helpers/elasticsearch_helper.rb' | ||
3 | + | ||
4 | +class ElasticsearchHelperTest < ActiveSupport::TestCase | ||
5 | + | ||
6 | + include ElasticsearchTestHelper | ||
7 | + include ElasticsearchHelper | ||
8 | + | ||
9 | + attr_accessor :params | ||
10 | + | ||
11 | + def indexed_models | ||
12 | + [Person,TextArticle,UploadedFile,Community,Event] | ||
13 | + end | ||
14 | + | ||
15 | + def create_instances | ||
16 | + create_user "Jose Abreu" | ||
17 | + create_user "Joao Abreu" | ||
18 | + create_user "Joana Abreu" | ||
19 | + create_user "Ana Abreu" | ||
20 | + end | ||
21 | + | ||
22 | + should 'return default_per_page when nil is passed' do | ||
23 | + assert_not_nil default_per_page nil | ||
24 | + assert_equal 10, default_per_page(nil) | ||
25 | + end | ||
26 | + | ||
27 | + should 'return default_per_page when per_page is passed' do | ||
28 | + assert_equal 15, default_per_page(15) | ||
29 | + end | ||
30 | + | ||
31 | + should 'have indexed_models in searchable_models' do | ||
32 | + assert_equivalent indexed_models, searchable_models | ||
33 | + end | ||
34 | + | ||
35 | + should 'return match_all if expression is blank' do | ||
36 | + assert_includes query_method.keys, :match_all | ||
37 | + end | ||
38 | + | ||
39 | + should 'return multi_match if expression is valid' do | ||
40 | + | ||
41 | + query= "my_query" | ||
42 | + fields = ['name','login'] | ||
43 | + result = query_method(query,fields) | ||
44 | + | ||
45 | + assert_includes result.keys, :multi_match | ||
46 | + assert_includes result[:multi_match][:query], query | ||
47 | + assert_equivalent result[:multi_match][:fields], fields | ||
48 | + end | ||
49 | + | ||
50 | + | ||
51 | + should 'return fields from models using weight' do | ||
52 | + class StubClass | ||
53 | + SEARCHABLE_FIELDS = {:name => {:weight => 10}, | ||
54 | + :login => {:weight => 20}, | ||
55 | + :description => {:weight => 2}} | ||
56 | + end | ||
57 | + | ||
58 | + expected = ["name^10", "login^20", "description^2"] | ||
59 | + assert_equivalent expected, fields_from_models([StubClass]) | ||
60 | + end | ||
61 | + | ||
62 | + should 'search from model Person sorted by Alphabetic' do | ||
63 | + self.params= {:selected_type => 'person', | ||
64 | + :selected_filter => 'lexical', | ||
65 | + :per_page => 4} | ||
66 | + | ||
67 | + result = process_results | ||
68 | + assert_equal ["Ana Abreu","Joana Abreu","Joao Abreu","Jose Abreu"], result.map(&:name) | ||
69 | + end | ||
70 | + | ||
71 | + should 'search from model Person sorted by More Recent' do | ||
72 | + self.params= {:selected_type => 'person', | ||
73 | + :selected_filter => 'more_recent', | ||
74 | + :per_page => 4} | ||
75 | + | ||
76 | + result = process_results | ||
77 | + assert_equal ["Jose Abreu","Joao Abreu","Joana Abreu","Ana Abreu"],result.map(&:name) | ||
78 | + end | ||
79 | + | ||
80 | + should 'search from model Person sorted by Relevance' do | ||
81 | + self.params= {:selected_type => 'person', | ||
82 | + :selected_filter => 'more_recent', | ||
83 | + :query => 'JOAO ABREU', | ||
84 | + :per_page => 4} | ||
85 | + | ||
86 | + result = process_results | ||
87 | + assert_equal ["Joao Abreu","Jose Abreu","Joana Abreu","Ana Abreu"],result.map(&:name) | ||
88 | + end | ||
89 | + | ||
90 | +end |
plugins/elasticsearch/test/unit/models/community_test.rb
@@ -8,10 +8,6 @@ class CommunityTest < ActionController::TestCase | @@ -8,10 +8,6 @@ class CommunityTest < ActionController::TestCase | ||
8 | [Community] | 8 | [Community] |
9 | end | 9 | end |
10 | 10 | ||
11 | - def setup | ||
12 | - super | ||
13 | - end | ||
14 | - | ||
15 | should 'index searchable fields for Community model' do | 11 | should 'index searchable fields for Community model' do |
16 | Community::SEARCHABLE_FIELDS.each do |key, value| | 12 | Community::SEARCHABLE_FIELDS.each do |key, value| |
17 | assert_includes indexed_fields(Community), key | 13 | assert_includes indexed_fields(Community), key |
plugins/elasticsearch/test/unit/models/event_test.rb
@@ -8,10 +8,6 @@ class EventTest < ActionController::TestCase | @@ -8,10 +8,6 @@ class EventTest < ActionController::TestCase | ||
8 | [Event] | 8 | [Event] |
9 | end | 9 | end |
10 | 10 | ||
11 | - def setup | ||
12 | - super | ||
13 | - end | ||
14 | - | ||
15 | should 'index searchable fields for Event model' do | 11 | should 'index searchable fields for Event model' do |
16 | Event::SEARCHABLE_FIELDS.each do |key, value| | 12 | Event::SEARCHABLE_FIELDS.each do |key, value| |
17 | assert_includes indexed_fields(Event), key | 13 | assert_includes indexed_fields(Event), key |
plugins/elasticsearch/test/unit/models/person_test.rb
@@ -8,10 +8,6 @@ class PersonTest < ActionController::TestCase | @@ -8,10 +8,6 @@ class PersonTest < ActionController::TestCase | ||
8 | [Person] | 8 | [Person] |
9 | end | 9 | end |
10 | 10 | ||
11 | - def setup | ||
12 | - super | ||
13 | - end | ||
14 | - | ||
15 | should 'index searchable fields for Person model' do | 11 | should 'index searchable fields for Person model' do |
16 | Person::SEARCHABLE_FIELDS.each do |key, value| | 12 | Person::SEARCHABLE_FIELDS.each do |key, value| |
17 | assert_includes indexed_fields(Person), key | 13 | assert_includes indexed_fields(Person), key |
@@ -24,5 +20,4 @@ class PersonTest < ActionController::TestCase | @@ -24,5 +20,4 @@ class PersonTest < ActionController::TestCase | ||
24 | assert_includes indexed_fields(Person)[key][:type], value[:type] || 'string' | 20 | assert_includes indexed_fields(Person)[key][:type], value[:type] || 'string' |
25 | end | 21 | end |
26 | end | 22 | end |
27 | - | ||
28 | end | 23 | end |
plugins/elasticsearch/test/unit/models/text_article_test.rb
@@ -8,10 +8,6 @@ class TextArticleTest < ActionController::TestCase | @@ -8,10 +8,6 @@ class TextArticleTest < ActionController::TestCase | ||
8 | [TextArticle] | 8 | [TextArticle] |
9 | end | 9 | end |
10 | 10 | ||
11 | - def setup | ||
12 | - super | ||
13 | - end | ||
14 | - | ||
15 | should 'index searchable fields for TextArticle model' do | 11 | should 'index searchable fields for TextArticle model' do |
16 | TextArticle::SEARCHABLE_FIELDS.each do |key, value| | 12 | TextArticle::SEARCHABLE_FIELDS.each do |key, value| |
17 | assert_includes indexed_fields(TextArticle), key | 13 | assert_includes indexed_fields(TextArticle), key |
plugins/elasticsearch/test/unit/models/uploaded_file_test.rb
@@ -8,10 +8,6 @@ class UploadedFileTest < ActionController::TestCase | @@ -8,10 +8,6 @@ class UploadedFileTest < ActionController::TestCase | ||
8 | [UploadedFile] | 8 | [UploadedFile] |
9 | end | 9 | end |
10 | 10 | ||
11 | - def setup | ||
12 | - super | ||
13 | - end | ||
14 | - | ||
15 | should 'index searchable fields for UploadedFile model' do | 11 | should 'index searchable fields for UploadedFile model' do |
16 | UploadedFile::SEARCHABLE_FIELDS.each do |key, value| | 12 | UploadedFile::SEARCHABLE_FIELDS.each do |key, value| |
17 | assert_includes indexed_fields(UploadedFile), key | 13 | assert_includes indexed_fields(UploadedFile), key |
plugins/elasticsearch/views/elasticsearch_plugin/_person_display.html.erb
@@ -7,7 +7,6 @@ | @@ -7,7 +7,6 @@ | ||
7 | <div class="body"> | 7 | <div class="body"> |
8 | <h2><%= link_to person.name, person.url %></h2> | 8 | <h2><%= link_to person.name, person.url %></h2> |
9 | <p><%= person.description %></p> | 9 | <p><%= person.description %></p> |
10 | - <%= person.created_at %> | ||
11 | </div> | 10 | </div> |
12 | </div> | 11 | </div> |
13 | </div> | 12 | </div> |