Commit e16d0e8c31a79f8aa309f52e14c6fb20d57b181e
1 parent
aedd0f8e
Exists in
elasticsearch_sort
Refactored controller and searching by api
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com>
Showing
15 changed files
with
268 additions
and
25 deletions
Show diff stats
plugins/elasticsearch/controllers/elasticsearch_plugin_controller.rb
... | ... | @@ -12,8 +12,27 @@ class ElasticsearchPluginController < ApplicationController |
12 | 12 | def search |
13 | 13 | define_searchable_types |
14 | 14 | define_search_fields_types |
15 | + define_results | |
16 | + end | |
17 | + | |
18 | + def define_results | |
19 | + @query = params[:query] | |
20 | + @results = process_results | |
21 | + end | |
15 | 22 | |
16 | - process_results | |
23 | + def define_searchable_types | |
24 | + @searchable_types = ElasticsearchHelper::searchable_types | |
25 | + @selected_type = (params[:selected_type]|| :all ).to_sym | |
17 | 26 | end |
18 | 27 | |
28 | + def define_search_fields_types | |
29 | + @search_filter_types = ElasticsearchHelper::search_filters | |
30 | + @selected_filter_field = (params[:selected_filter_field] || ElasticsearchHelper::search_filters.keys.first).to_sym | |
31 | + end | |
32 | + | |
33 | + private | |
34 | + | |
35 | +# def permit_params | |
36 | +# params.require(:per_page, :query) | |
37 | +# end | |
19 | 38 | end | ... | ... |
... | ... | @@ -0,0 +1,91 @@ |
1 | +module ElasticsearchHelper | |
2 | + | |
3 | + def self.searchable_types | |
4 | + { | |
5 | + :all => { label: _("All Results")}, | |
6 | + :community => { label: _("Communities")}, | |
7 | + :event => { label: _("Events")}, | |
8 | + :person => { label: _("People")} | |
9 | + } | |
10 | + end | |
11 | + | |
12 | + def self.search_filters | |
13 | + { | |
14 | + :lexical => { label: _("Alphabetical Order")}, | |
15 | + :recent => { label: _("More Recent Order")}, | |
16 | + :access => { label: _("More accessed")} | |
17 | + } | |
18 | + end | |
19 | + | |
20 | + def fields_from_model | |
21 | + klass::SEARCHABLE_FIELDS.map do |key, value| | |
22 | + if value[:weight] | |
23 | + "#{key}^#{value[:weight]}" | |
24 | + else | |
25 | + "#{key}" | |
26 | + end | |
27 | + end | |
28 | + end | |
29 | + | |
30 | + def get_query text, klass=nil | |
31 | + query = {} | |
32 | + unless text.blank? | |
33 | + text = text.downcase | |
34 | + query = { | |
35 | + query: { | |
36 | + match_all: { | |
37 | + } | |
38 | + }, | |
39 | + filter: { | |
40 | + regexp: { | |
41 | + name: { | |
42 | + value: ".*" + text + ".*" } | |
43 | + } | |
44 | + }, | |
45 | + suggest: { | |
46 | + autocomplete: { | |
47 | + text: text, | |
48 | + term: { | |
49 | + field: "name", | |
50 | + suggest_mode: "always" | |
51 | + } | |
52 | + } | |
53 | + } | |
54 | + | |
55 | + } | |
56 | + end | |
57 | + query | |
58 | + end | |
59 | + | |
60 | + def process_results | |
61 | + selected_type = (params[:selected_type]|| :all).to_sym | |
62 | + if selected_type == :all | |
63 | + search_from_all_models | |
64 | + else | |
65 | + search_from_model selected_type | |
66 | + end | |
67 | + end | |
68 | + | |
69 | + def search_from_all_models | |
70 | + models = [] | |
71 | + query = get_query params[:query] | |
72 | + | |
73 | + ElasticsearchHelper::searchable_types.keys.each {| model | models.append( model.to_s.classify.constantize) if model != :all } | |
74 | + Elasticsearch::Model.search(query, models, size: default_per_page(params[:per_page])).page(params[:page]).records | |
75 | + end | |
76 | + | |
77 | + def search_from_model model | |
78 | + begin | |
79 | + klass = model.to_s.classify.constantize | |
80 | + query = get_query params[:query], klass | |
81 | + klass.search(query, size: default_per_page(params[:per_page])).page(params[:page]).records | |
82 | + rescue | |
83 | + [] | |
84 | + end | |
85 | + end | |
86 | + | |
87 | + def default_per_page per_page | |
88 | + per_page ||= 10 | |
89 | + end | |
90 | + | |
91 | +end | ... | ... |
plugins/elasticsearch/lib/elasticsearch_plugin/api.rb
1 | 1 | require_relative '../../helpers/elasticsearch_helper' |
2 | - | |
2 | +require_relative 'entities' | |
3 | 3 | |
4 | 4 | class ElasticsearchPlugin::API < Grape::API |
5 | 5 | include Api::Helpers |
6 | + helpers ElasticsearchHelper | |
6 | 7 | |
7 | 8 | resource :search do |
8 | 9 | get do |
9 | - present target, :with => Api::Entities::Person | |
10 | + target = process_results | |
11 | + present target, | |
12 | + :with => Elasticsearch::Entities::Result, | |
13 | + :types => ElasticsearchHelper.searchable_types.except(:all).keys.map { |key| key.to_s.classify } | |
10 | 14 | end |
11 | 15 | |
12 | 16 | get 'types' do |
13 | - types = {types: ElasticsearchHelper::SEARCHABLE_TYPES.stringify_keys.keys} | |
17 | + types = {types: ElasticsearchHelper::searchable_types.stringify_keys.keys} | |
14 | 18 | present types, with: Grape::Presenters::Presenter |
15 | 19 | end |
16 | 20 | ... | ... |
plugins/elasticsearch/lib/elasticsearch_plugin/entities.rb
0 → 100644
... | ... | @@ -0,0 +1,17 @@ |
1 | +module Elasticsearch | |
2 | + module Entities | |
3 | + class Result < Api::Entity | |
4 | + root "results","result" | |
5 | + | |
6 | + expose :type do |object, options| | |
7 | + options[:types].detect { |type| type.to_s.upcase if object.is_a? (type.to_s.classify.constantize) } | |
8 | + end | |
9 | + | |
10 | + expose :name | |
11 | + | |
12 | + expose :author, if: lambda { |object,options| object.respond_to? 'author'} do |object, options| | |
13 | + object.author.present? ? object.author.name : "" | |
14 | + end | |
15 | + end | |
16 | + end | |
17 | +end | ... | ... |
plugins/elasticsearch/lib/ext/text_article.rb
plugins/elasticsearch/lib/ext/uploaded_file.rb
plugins/elasticsearch/test/test_helper.rb
1 | 1 | require 'test_helper' |
2 | +require_relative '../../../test/api/test_helper.rb' | |
2 | 3 | |
3 | -class ElasticsearchTestHelper < ActionController::TestCase | |
4 | +module ElasticsearchTestHelper | |
4 | 5 | |
5 | 6 | def setup |
6 | 7 | setup_environment |
8 | + create_instances | |
7 | 9 | import_instancies |
8 | 10 | end |
9 | 11 | |
12 | + def create_instances | |
13 | + end | |
14 | + | |
10 | 15 | def teardown |
11 | 16 | indexed_models.each {|model| |
12 | 17 | model.__elasticsearch__.client.indices.delete index: model.index_name |
... | ... | @@ -16,9 +21,10 @@ class ElasticsearchTestHelper < ActionController::TestCase |
16 | 21 | def import_instancies |
17 | 22 | indexed_models.each {|model| |
18 | 23 | model.__elasticsearch__.create_index! |
24 | + sleep 2 | |
19 | 25 | model.import |
26 | + sleep 1 | |
20 | 27 | } |
21 | - sleep 2 | |
22 | 28 | end |
23 | 29 | |
24 | 30 | def setup_environment |
... | ... | @@ -31,7 +37,7 @@ class ElasticsearchTestHelper < ActionController::TestCase |
31 | 37 | end |
32 | 38 | |
33 | 39 | def indexed_fields model |
34 | - model.mappings.to_hash[model.name.downcase.to_sym][:properties] | |
40 | + model.mappings.to_hash[model.name.underscore.to_sym][:properties] | |
35 | 41 | end |
36 | 42 | |
37 | 43 | end | ... | ... |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_api_test.rb
0 → 100644
... | ... | @@ -0,0 +1,51 @@ |
1 | +require "#{File.dirname(__FILE__)}/../../test_helper" | |
2 | + | |
3 | +class ElasticsearchPluginApiTest < ActiveSupport::TestCase | |
4 | + | |
5 | + include ElasticsearchTestHelper | |
6 | + | |
7 | + def indexed_models | |
8 | + [Community, Person] | |
9 | + end | |
10 | + | |
11 | + def create_instances | |
12 | + 7.times.each {|index| create_user "person_#{index}"} | |
13 | + 4.times.each {|index| fast_create Community, name: "community_#{index}", created_at: Date.new } | |
14 | + end | |
15 | + | |
16 | + should 'show all types avaliable in /search/types endpoint' do | |
17 | + get "/api/v1/search/types" | |
18 | + json = JSON.parse(last_response.body) | |
19 | + assert_equal 200, last_response.status | |
20 | + assert_equal ElasticsearchHelper::searchable_types.stringify_keys.keys, json["types"] | |
21 | + end | |
22 | + | |
23 | + should 'respond with endpoint /search with more than 10 results' do | |
24 | + get "/api/v1/search" | |
25 | + json = JSON.parse(last_response.body) | |
26 | + assert_equal 200, last_response.status | |
27 | + assert_equal 10, json["results"].count | |
28 | + end | |
29 | + | |
30 | + should 'respond with query in downcase' do | |
31 | + get "/api/v1/search?query=person_" | |
32 | + json = JSON.parse(last_response.body) | |
33 | + assert_equal 200, last_response.status | |
34 | + assert_equal 7, json["results"].count | |
35 | + end | |
36 | + | |
37 | + should 'respond with query in upcase' do | |
38 | + get "/api/v1/search?query=PERSON_" | |
39 | + json = JSON.parse(last_response.body) | |
40 | + assert_equal 200, last_response.status | |
41 | + assert_equal 7, json["results"].count | |
42 | + end | |
43 | + | |
44 | + should 'respond with selected_type' do | |
45 | + get "/api/v1/search?selected_type=community" | |
46 | + json = JSON.parse(last_response.body) | |
47 | + assert_equal 200, last_response.status | |
48 | + assert_equal 4, json["results"].count | |
49 | + end | |
50 | + | |
51 | +end | ... | ... |
plugins/elasticsearch/test/unit/controllers/elasticsearch_plugin_controller_test.rb
1 | 1 | require "#{File.dirname(__FILE__)}/../../test_helper" |
2 | 2 | |
3 | -class ElasticsearchPluginControllerTest < ElasticsearchTestHelper | |
3 | +class ElasticsearchPluginControllerTest < ActionController::TestCase | |
4 | + | |
5 | + include ElasticsearchTestHelper | |
4 | 6 | |
5 | 7 | def indexed_models |
6 | 8 | [Community, Person] |
7 | 9 | end |
8 | 10 | |
9 | - def setup | |
10 | - create_instances | |
11 | - super | |
12 | - end | |
13 | - | |
14 | - def teardown | |
15 | - super | |
16 | - end | |
17 | - | |
18 | 11 | def create_instances |
19 | 12 | create_people |
20 | 13 | create_communities | ... | ... |
plugins/elasticsearch/test/unit/elasticsearch_test.rb
plugins/elasticsearch/test/unit/models/community_test.rb
plugins/elasticsearch/test/unit/models/event_test.rb
plugins/elasticsearch/test/unit/models/person_test.rb
plugins/elasticsearch/test/unit/models/text_article_test.rb
0 → 100644
... | ... | @@ -0,0 +1,28 @@ |
1 | +require "#{File.dirname(__FILE__)}/../../test_helper" | |
2 | + | |
3 | +class TextArticleTest < ActionController::TestCase | |
4 | + | |
5 | + include ElasticsearchTestHelper | |
6 | + | |
7 | + def indexed_models | |
8 | + [TextArticle] | |
9 | + end | |
10 | + | |
11 | + def setup | |
12 | + super | |
13 | + end | |
14 | + | |
15 | + should 'index searchable fields for TextArticle model' do | |
16 | + TextArticle::SEARCHABLE_FIELDS.each do |key, value| | |
17 | + assert_includes indexed_fields(TextArticle), key | |
18 | + end | |
19 | + end | |
20 | + | |
21 | + should 'index control fields for TextArticle model' do | |
22 | + TextArticle::control_fields.each do |key, value| | |
23 | + assert_includes indexed_fields(TextArticle), key | |
24 | + assert_includes indexed_fields(TextArticle)[key][:type], value[:type] || 'string' | |
25 | + end | |
26 | + end | |
27 | + | |
28 | +end | ... | ... |
plugins/elasticsearch/test/unit/models/uploaded_file_test.rb
0 → 100644
... | ... | @@ -0,0 +1,28 @@ |
1 | +require "#{File.dirname(__FILE__)}/../../test_helper" | |
2 | + | |
3 | +class UploadedFileTest < ActionController::TestCase | |
4 | + | |
5 | + include ElasticsearchTestHelper | |
6 | + | |
7 | + def indexed_models | |
8 | + [UploadedFile] | |
9 | + end | |
10 | + | |
11 | + def setup | |
12 | + super | |
13 | + end | |
14 | + | |
15 | + should 'index searchable fields for UploadedFile model' do | |
16 | + UploadedFile::SEARCHABLE_FIELDS.each do |key, value| | |
17 | + assert_includes indexed_fields(UploadedFile), key | |
18 | + end | |
19 | + end | |
20 | + | |
21 | + should 'index control fields for UploadedFile model' do | |
22 | + UploadedFile::control_fields.each do |key, value| | |
23 | + assert_includes indexed_fields(UploadedFile), key | |
24 | + assert_includes indexed_fields(UploadedFile)[key][:type], value[:type].presence || 'string' | |
25 | + end | |
26 | + end | |
27 | + | |
28 | +end | ... | ... |