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 | 19 | } |
20 | 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 | 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 | 25 | end |
53 | 26 | |
27 | + private | |
28 | + | |
54 | 29 | def search_from_all_models |
55 | 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 | 32 | end |
59 | 33 | |
60 | 34 | def search_from_model model |
... | ... | @@ -68,17 +42,28 @@ module ElasticsearchHelper |
68 | 42 | end |
69 | 43 | end |
70 | 44 | |
71 | - def default_per_page per_page | |
45 | + def default_per_page per_page=nil | |
72 | 46 | per_page ||= 10 |
73 | 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 | 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 | 64 | end |
80 | 65 | |
81 | - def query_method expression, fields | |
66 | + def query_method expression="", fields=[] | |
82 | 67 | query_exp = {} |
83 | 68 | if expression.blank? |
84 | 69 | query_exp = { |
... | ... | @@ -107,8 +92,21 @@ module ElasticsearchHelper |
107 | 92 | } |
108 | 93 | |
109 | 94 | query[:sort] = [sort_by,"_score"] if sort_by |
110 | - | |
111 | 95 | query |
112 | 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 | 112 | end | ... | ... |
plugins/elasticsearch/lib/elasticsearch_plugin/entities.rb
1 | 1 | module Elasticsearch |
2 | 2 | module Entities |
3 | + | |
3 | 4 | class Result < Api::Entity |
4 | 5 | root "results","result" |
5 | 6 | |
... | ... | @@ -7,11 +8,24 @@ module Elasticsearch |
7 | 8 | options[:types].detect { |type| type.to_s.upcase if object.is_a? (type.to_s.classify.constantize) } |
8 | 9 | end |
9 | 10 | |
11 | + expose :id | |
10 | 12 | expose :name |
11 | 13 | |
12 | 14 | expose :author, if: lambda { |object,options| object.respond_to? 'author'} do |object, options| |
13 | 15 | object.author.present? ? object.author.name : "" |
14 | 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 | 28 | end |
29 | + | |
16 | 30 | end |
17 | 31 | end | ... | ... |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_api_test.rb
... | ... | @@ -10,7 +10,7 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase |
10 | 10 | |
11 | 11 | def create_instances |
12 | 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 | 14 | end |
15 | 15 | |
16 | 16 | should 'show all types avaliable in /search/types endpoint' do |
... | ... | @@ -47,5 +47,4 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase |
47 | 47 | assert_equal 200, last_response.status |
48 | 48 | assert_equal 4, json["results"].count |
49 | 49 | end |
50 | - | |
51 | 50 | end | ... | ... |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_entities_test.rb
0 → 100644
... | ... | @@ -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 @@ |
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 | 8 | [Community] |
9 | 9 | end |
10 | 10 | |
11 | - def setup | |
12 | - super | |
13 | - end | |
14 | - | |
15 | 11 | should 'index searchable fields for Community model' do |
16 | 12 | Community::SEARCHABLE_FIELDS.each do |key, value| |
17 | 13 | assert_includes indexed_fields(Community), key | ... | ... |
plugins/elasticsearch/test/unit/models/event_test.rb
... | ... | @@ -8,10 +8,6 @@ class EventTest < ActionController::TestCase |
8 | 8 | [Event] |
9 | 9 | end |
10 | 10 | |
11 | - def setup | |
12 | - super | |
13 | - end | |
14 | - | |
15 | 11 | should 'index searchable fields for Event model' do |
16 | 12 | Event::SEARCHABLE_FIELDS.each do |key, value| |
17 | 13 | assert_includes indexed_fields(Event), key | ... | ... |
plugins/elasticsearch/test/unit/models/person_test.rb
... | ... | @@ -8,10 +8,6 @@ class PersonTest < ActionController::TestCase |
8 | 8 | [Person] |
9 | 9 | end |
10 | 10 | |
11 | - def setup | |
12 | - super | |
13 | - end | |
14 | - | |
15 | 11 | should 'index searchable fields for Person model' do |
16 | 12 | Person::SEARCHABLE_FIELDS.each do |key, value| |
17 | 13 | assert_includes indexed_fields(Person), key |
... | ... | @@ -24,5 +20,4 @@ class PersonTest < ActionController::TestCase |
24 | 20 | assert_includes indexed_fields(Person)[key][:type], value[:type] || 'string' |
25 | 21 | end |
26 | 22 | end |
27 | - | |
28 | 23 | end | ... | ... |
plugins/elasticsearch/test/unit/models/text_article_test.rb
... | ... | @@ -8,10 +8,6 @@ class TextArticleTest < ActionController::TestCase |
8 | 8 | [TextArticle] |
9 | 9 | end |
10 | 10 | |
11 | - def setup | |
12 | - super | |
13 | - end | |
14 | - | |
15 | 11 | should 'index searchable fields for TextArticle model' do |
16 | 12 | TextArticle::SEARCHABLE_FIELDS.each do |key, value| |
17 | 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 | 8 | [UploadedFile] |
9 | 9 | end |
10 | 10 | |
11 | - def setup | |
12 | - super | |
13 | - end | |
14 | - | |
15 | 11 | should 'index searchable fields for UploadedFile model' do |
16 | 12 | UploadedFile::SEARCHABLE_FIELDS.each do |key, value| |
17 | 13 | assert_includes indexed_fields(UploadedFile), key | ... | ... |
plugins/elasticsearch/views/elasticsearch_plugin/_person_display.html.erb