Commit 67d0efad136aa2fcf6d2cf601be59bed05de091f
Committed by
Macartur Sousa
1 parent
873bf3f0
Exists in
fix_sign_up_form
Elasticsearch: Adding sort and some fixings
* Sort documents by name * Adds lexical sort for searchs without expression * Sort by name.raw instead of name * Indexes models by raw nested in name, remove suggests * Fixes tests and alphabetical ordering * Adds created at as a type of sort * Fixing search using sort by * Fixed Sort by to receive filter param * Fixed noosfero to be support noosfero links * Fixed text_articles and upload_files extensions * Fixed api tests * Refactored elasticsearch_plugin and elasticsearch_api * Fixed to use partial query * Fixed sort and query_string Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com>
Showing
25 changed files
with
389 additions
and
135 deletions
Show diff stats
plugins/elasticsearch/Rakefile
@@ -30,7 +30,7 @@ task :start do | @@ -30,7 +30,7 @@ task :start do | ||
30 | if elasticsearch_development | 30 | if elasticsearch_development |
31 | sh 'sudo systemctl start elasticsearch >> /dev/null 2>&1' | 31 | sh 'sudo systemctl start elasticsearch >> /dev/null 2>&1' |
32 | sh 'sudo systemctl enable elasticsearch >> /dev/null 2>&1' | 32 | sh 'sudo systemctl enable elasticsearch >> /dev/null 2>&1' |
33 | - sleep 2 | 33 | + sleep 10 |
34 | end | 34 | end |
35 | end | 35 | end |
36 | 36 |
plugins/elasticsearch/controllers/elasticsearch_plugin_controller.rb
@@ -18,6 +18,7 @@ class ElasticsearchPluginController < ApplicationController | @@ -18,6 +18,7 @@ class ElasticsearchPluginController < ApplicationController | ||
18 | def define_results | 18 | def define_results |
19 | @query = params[:query] | 19 | @query = params[:query] |
20 | @results = process_results | 20 | @results = process_results |
21 | + @hits = @results.total | ||
21 | end | 22 | end |
22 | 23 | ||
23 | def define_searchable_types | 24 | def define_searchable_types |
@@ -26,13 +27,8 @@ class ElasticsearchPluginController < ApplicationController | @@ -26,13 +27,8 @@ class ElasticsearchPluginController < ApplicationController | ||
26 | end | 27 | end |
27 | 28 | ||
28 | def define_search_fields_types | 29 | 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 | 30 | + @filter_types = ElasticsearchHelper::filters |
31 | + @selected_filter = (params[:filter] || :relevance).to_sym | ||
31 | end | 32 | end |
32 | 33 | ||
33 | - private | ||
34 | - | ||
35 | -# def permit_params | ||
36 | -# params.require(:per_page, :query) | ||
37 | -# end | ||
38 | end | 34 | end |
plugins/elasticsearch/helpers/elasticsearch_helper.rb
@@ -11,83 +11,99 @@ module ElasticsearchHelper | @@ -11,83 +11,99 @@ module ElasticsearchHelper | ||
11 | } | 11 | } |
12 | end | 12 | end |
13 | 13 | ||
14 | - def self.search_filters | 14 | + def self.filters |
15 | { | 15 | { |
16 | - :lexical => { label: _("Alphabetical Order")}, | ||
17 | - :recent => { label: _("More Recent Order")}, | ||
18 | - :access => { label: _("More accessed")} | 16 | + :relevance => { label: _("Relevance")}, |
17 | + :lexical => { label: _("Alphabetical")}, | ||
18 | + :more_recent => { label: _("More Recent")}, | ||
19 | } | 19 | } |
20 | end | 20 | end |
21 | 21 | ||
22 | - def fields_from_model | ||
23 | - klass::SEARCHABLE_FIELDS.map do |key, value| | ||
24 | - if value[:weight] | ||
25 | - "#{key}^#{value[:weight]}" | ||
26 | - else | ||
27 | - "#{key}" | ||
28 | - end | ||
29 | - end | ||
30 | - end | ||
31 | - | ||
32 | - def get_query text, klass=nil | ||
33 | - query = {} | ||
34 | - unless text.blank? | ||
35 | - text = text.downcase | ||
36 | - query = { | ||
37 | - query: { | ||
38 | - match_all: { | ||
39 | - } | ||
40 | - }, | ||
41 | - filter: { | ||
42 | - regexp: { | ||
43 | - name: { | ||
44 | - value: ".*" + text + ".*" } | ||
45 | - } | ||
46 | - }, | ||
47 | - suggest: { | ||
48 | - autocomplete: { | ||
49 | - text: text, | ||
50 | - term: { | ||
51 | - field: "name", | ||
52 | - suggest_mode: "always" | ||
53 | - } | ||
54 | - } | ||
55 | - } | ||
56 | - | ||
57 | - } | ||
58 | - end | ||
59 | - query | ||
60 | - end | ||
61 | - | ||
62 | def process_results | 22 | def process_results |
63 | - selected_type = (params[:selected_type]|| :all).to_sym | ||
64 | - if selected_type == :all | ||
65 | - search_from_all_models | ||
66 | - else | ||
67 | - search_from_model selected_type | ||
68 | - end | 23 | + selected_type = (params[:selected_type].presence|| :all).to_sym |
24 | + selected_type == :all ? search_from_all_models : search_from_model(selected_type) | ||
69 | end | 25 | end |
70 | 26 | ||
71 | - def search_from_all_models | ||
72 | - models = [] | ||
73 | - query = get_query params[:query] | 27 | + private |
74 | 28 | ||
75 | - ElasticsearchHelper::searchable_types.keys.each {| model | models.append( model.to_s.classify.constantize) if model != :all } | ||
76 | - Elasticsearch::Model.search(query, models, size: default_per_page(params[:per_page])).page(params[:page]).records | 29 | + def search_from_all_models |
30 | + query = get_query params[:query], sort_by: get_sort_by(params[:filter]) | ||
31 | + Elasticsearch::Model.search(query,searchable_models, size: default_per_page(params[:per_page])).page(params[:page]).records | ||
77 | end | 32 | end |
78 | 33 | ||
79 | def search_from_model model | 34 | def search_from_model model |
80 | begin | 35 | begin |
81 | klass = model.to_s.classify.constantize | 36 | klass = model.to_s.classify.constantize |
82 | - query = get_query params[:query], klass | 37 | + |
38 | + query = get_query params[:query], klass: klass, sort_by: get_sort_by(params[:filter]) | ||
83 | klass.search(query, size: default_per_page(params[:per_page])).page(params[:page]).records | 39 | klass.search(query, size: default_per_page(params[:per_page])).page(params[:page]).records |
84 | rescue | 40 | rescue |
85 | [] | 41 | [] |
86 | end | 42 | end |
87 | end | 43 | end |
88 | 44 | ||
89 | - def default_per_page per_page | 45 | + def default_per_page per_page=nil |
90 | per_page ||= 10 | 46 | per_page ||= 10 |
91 | end | 47 | end |
92 | 48 | ||
49 | + def get_sort_by sort_by | ||
50 | + case sort_by | ||
51 | + when "lexical" | ||
52 | + { "name.raw" => {"order" => "asc" }} | ||
53 | + when "more_recent" | ||
54 | + { "created_at" => {"order" => "desc"}} | ||
55 | + end | ||
56 | + end | ||
57 | + | ||
58 | + def searchable_models | ||
59 | + begin | ||
60 | + ElasticsearchHelper::searchable_types.except(:all).keys.map { | model | model.to_s.classify.constantize } | ||
61 | + rescue | ||
62 | + [] | ||
63 | + end | ||
64 | + end | ||
65 | + | ||
66 | + def query_method expression="", fields=[] | ||
67 | + query_exp = {} | ||
68 | + if expression.blank? | ||
69 | + else | ||
70 | + query_exp = { | ||
71 | + query: { | ||
72 | + query_string: { | ||
73 | + query: "*"+expression.downcase.split.join('* *')+"*", | ||
74 | + fields: fields, | ||
75 | + tie_breaker: 0.4, | ||
76 | + minimum_should_match: "100%" | ||
77 | + }, | ||
78 | + } | ||
79 | + } | ||
80 | + end | ||
81 | + query_exp | ||
82 | + end | ||
83 | + | ||
84 | + def get_query text="", options={} | ||
85 | + klass = options[:klass] | ||
86 | + sort_by = options[:sort_by] | ||
87 | + | ||
88 | + fields = klass.nil? ? (fields_from_models searchable_models) : (fields_from_models [klass]) | ||
89 | + | ||
90 | + query = query_method(text, fields) | ||
91 | + query[:sort] = sort_by if sort_by | ||
92 | + query | ||
93 | + end | ||
94 | + | ||
95 | + def fields_from_models klasses | ||
96 | + fields = Set.new | ||
97 | + klasses.each do |klass| | ||
98 | + klass::SEARCHABLE_FIELDS.map do |key, value| | ||
99 | + if value and value[:weight] | ||
100 | + fields.add "#{key}^#{value[:weight]}" | ||
101 | + else | ||
102 | + fields.add "#{key}" | ||
103 | + end | ||
104 | + end | ||
105 | + end | ||
106 | + fields.to_a | ||
107 | + end | ||
108 | + | ||
93 | end | 109 | end |
plugins/elasticsearch/lib/elasticsearch_indexed_model.rb
@@ -2,14 +2,21 @@ module ElasticsearchIndexedModel | @@ -2,14 +2,21 @@ module ElasticsearchIndexedModel | ||
2 | 2 | ||
3 | def self.included base | 3 | def self.included base |
4 | base.send :include, Elasticsearch::Model | 4 | base.send :include, Elasticsearch::Model |
5 | + base.send :include, Elasticsearch::Model::Callbacks | ||
6 | + | ||
5 | base.send :index_name, "#{Rails.env}_#{base.index_name}" | 7 | base.send :index_name, "#{Rails.env}_#{base.index_name}" |
6 | base.extend ClassMethods | 8 | base.extend ClassMethods |
7 | base.class_eval do | 9 | base.class_eval do |
8 | settings index: { number_of_shards: 1 } do | 10 | settings index: { number_of_shards: 1 } do |
9 | mappings dynamic: 'false' do | 11 | mappings dynamic: 'false' do |
10 | - base.indexable_fields.each do |field, value| | 12 | + base.indexed_fields.each do |field, value| |
11 | value = {} if value.nil? | 13 | value = {} if value.nil? |
12 | - indexes field, type: value[:type].presence | 14 | + type = value[:type].presence |
15 | + if type.nil? | ||
16 | + indexes(field, fields: base.raw_field(field)) | ||
17 | + else | ||
18 | + indexes field, type: type | ||
19 | + end | ||
13 | print '.' | 20 | print '.' |
14 | end | 21 | end |
15 | end | 22 | end |
@@ -28,9 +35,19 @@ module ElasticsearchIndexedModel | @@ -28,9 +35,19 @@ module ElasticsearchIndexedModel | ||
28 | end | 35 | end |
29 | 36 | ||
30 | module ClassMethods | 37 | module ClassMethods |
31 | - def indexable_fields | ||
32 | - self::SEARCHABLE_FIELDS.update self.control_fields | 38 | + def raw_field name |
39 | + { | ||
40 | + raw: { | ||
41 | + type: "string", | ||
42 | + index: "not_analyzed" | ||
43 | + } | ||
44 | + } | ||
45 | + end | ||
46 | + | ||
47 | + def indexed_fields | ||
48 | + self::SEARCHABLE_FIELDS.merge self.control_fields | ||
33 | end | 49 | end |
50 | + | ||
34 | end | 51 | end |
35 | 52 | ||
36 | end | 53 | end |
plugins/elasticsearch/lib/elasticsearch_plugin.rb
@@ -17,12 +17,24 @@ class ElasticsearchPlugin < Noosfero::Plugin | @@ -17,12 +17,24 @@ class ElasticsearchPlugin < Noosfero::Plugin | ||
17 | end | 17 | end |
18 | 18 | ||
19 | def search_controller_filters | 19 | def search_controller_filters |
20 | - block = proc do | ||
21 | - redirect_to controller: 'elasticsearch_plugin', action: 'search', params: params | ||
22 | - end | 20 | + block = proc do |
21 | + | ||
22 | + case action_name | ||
23 | + when 'contents' | ||
24 | + params[:selected_type] = :text_article | ||
25 | + when 'index' | ||
26 | + when 'articles' | ||
27 | + params[:selected_type] = :text_article | ||
28 | + else | ||
29 | + params[:selected_type] = action_name.singularize.to_sym | ||
30 | + end | ||
31 | + | ||
32 | + redirect_to controller: 'elasticsearch_plugin', action: 'search', params: params | ||
33 | + end | ||
23 | 34 | ||
24 | [{ :type => 'before_filter', | 35 | [{ :type => 'before_filter', |
25 | :method_name => 'redirect_search_to_elastic', | 36 | :method_name => 'redirect_search_to_elastic', |
26 | :block => block }] | 37 | :block => block }] |
27 | end | 38 | end |
39 | + | ||
28 | end | 40 | 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/lib/ext/community.rb
@@ -3,7 +3,9 @@ require_relative '../elasticsearch_indexed_model' | @@ -3,7 +3,9 @@ require_relative '../elasticsearch_indexed_model' | ||
3 | 3 | ||
4 | class Community | 4 | class Community |
5 | def self.control_fields | 5 | def self.control_fields |
6 | - {} | 6 | + { |
7 | + :created_at => {type: 'date'} | ||
8 | + } | ||
7 | end | 9 | end |
8 | include ElasticsearchIndexedModel | 10 | include ElasticsearchIndexedModel |
9 | end | 11 | end |
plugins/elasticsearch/lib/ext/event.rb
plugins/elasticsearch/lib/ext/person.rb
@@ -6,6 +6,7 @@ class Person | @@ -6,6 +6,7 @@ class Person | ||
6 | { | 6 | { |
7 | :visible => {type: 'boolean'}, | 7 | :visible => {type: 'boolean'}, |
8 | :public_profile => {type: 'boolean'}, | 8 | :public_profile => {type: 'boolean'}, |
9 | + :created_at => {type: 'date'} | ||
9 | } | 10 | } |
10 | end | 11 | end |
11 | include ElasticsearchIndexedModel | 12 | include ElasticsearchIndexedModel |
plugins/elasticsearch/lib/ext/text_article.rb
1 | +# REQUIRE TO LOAD DESCENDANTS FROM TEXT_ARTICLE | ||
2 | +require_dependency 'raw_html_article' | ||
3 | +require_dependency 'tiny_mce_article' | ||
4 | + | ||
1 | require_dependency 'text_article' | 5 | require_dependency 'text_article' |
2 | require_relative '../elasticsearch_indexed_model' | 6 | require_relative '../elasticsearch_indexed_model' |
3 | 7 | ||
@@ -6,6 +10,7 @@ class TextArticle | @@ -6,6 +10,7 @@ class TextArticle | ||
6 | { | 10 | { |
7 | :advertise => {}, | 11 | :advertise => {}, |
8 | :published => {}, | 12 | :published => {}, |
13 | + :created_at => {type: 'date'} | ||
9 | } | 14 | } |
10 | end | 15 | end |
11 | include ElasticsearchIndexedModel | 16 | include ElasticsearchIndexedModel |
plugins/elasticsearch/lib/ext/uploaded_file.rb
plugins/elasticsearch/test/test_helper.rb
@@ -20,7 +20,7 @@ module ElasticsearchTestHelper | @@ -20,7 +20,7 @@ module ElasticsearchTestHelper | ||
20 | model.__elasticsearch__.create_index! force: true | 20 | model.__elasticsearch__.create_index! force: true |
21 | model.import | 21 | model.import |
22 | } | 22 | } |
23 | - sleep 1 | 23 | + sleep 2 |
24 | end | 24 | end |
25 | 25 | ||
26 | def setup_environment | 26 | def setup_environment |
plugins/elasticsearch/test/unit/api/elasticsearch_plugin_api_test.rb
@@ -9,8 +9,8 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | @@ -9,8 +9,8 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | ||
9 | end | 9 | end |
10 | 10 | ||
11 | def create_instances | 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 } | 12 | + 7.times.each {|index| create_user "person #{index}"} |
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 |
@@ -28,14 +28,14 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | @@ -28,14 +28,14 @@ class ElasticsearchPluginApiTest < ActiveSupport::TestCase | ||
28 | end | 28 | end |
29 | 29 | ||
30 | should 'respond with query in downcase' do | 30 | should 'respond with query in downcase' do |
31 | - get "/api/v1/search?query=person_" | 31 | + get "/api/v1/search?query=person" |
32 | json = JSON.parse(last_response.body) | 32 | json = JSON.parse(last_response.body) |
33 | assert_equal 200, last_response.status | 33 | assert_equal 200, last_response.status |
34 | assert_equal 7, json["results"].count | 34 | assert_equal 7, json["results"].count |
35 | end | 35 | end |
36 | 36 | ||
37 | - should 'respond with query in upcase' do | ||
38 | - get "/api/v1/search?query=PERSON_" | 37 | + should 'respond with query in uppercase' do |
38 | + get "/api/v1/search?query=PERSON" | ||
39 | json = JSON.parse(last_response.body) | 39 | json = JSON.parse(last_response.body) |
40 | assert_equal 200, last_response.status | 40 | assert_equal 200, last_response.status |
41 | assert_equal 7, json["results"].count | 41 | assert_equal 7, json["results"].count |
@@ -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/controllers/elasticsearch_plugin_controller_test.rb
@@ -15,13 +15,13 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | @@ -15,13 +15,13 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | ||
15 | 15 | ||
16 | def create_people | 16 | def create_people |
17 | 5.times do | index | | 17 | 5.times do | index | |
18 | - create_user "person_#{index}" | 18 | + create_user "person #{index}" |
19 | end | 19 | end |
20 | end | 20 | end |
21 | 21 | ||
22 | def create_communities | 22 | def create_communities |
23 | 6.times do | index | | 23 | 6.times do | index | |
24 | - fast_create Community, name: "community_#{index}", created_at: Date.new | 24 | + fast_create Community, name: "community #{index}", created_at: Date.new |
25 | end | 25 | end |
26 | end | 26 | end |
27 | 27 | ||
@@ -30,8 +30,8 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | @@ -30,8 +30,8 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | ||
30 | assert_response :success | 30 | assert_response :success |
31 | assert_not_nil assigns(:searchable_types) | 31 | assert_not_nil assigns(:searchable_types) |
32 | assert_not_nil assigns(:selected_type) | 32 | assert_not_nil assigns(:selected_type) |
33 | - assert_not_nil assigns(:search_filter_types) | ||
34 | - assert_not_nil assigns(:selected_filter_field) | 33 | + assert_not_nil assigns(:filter_types) |
34 | + assert_not_nil assigns(:selected_filter) | ||
35 | end | 35 | end |
36 | 36 | ||
37 | should 'return 10 results if selected_type is nil and query is nil' do | 37 | should 'return 10 results if selected_type is nil and query is nil' do |
@@ -54,31 +54,31 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | @@ -54,31 +54,31 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | ||
54 | end | 54 | end |
55 | 55 | ||
56 | should 'return results filtered by query' do | 56 | should 'return results filtered by query' do |
57 | - get :index, { 'query' => "person_"} | 57 | + get :index, { 'query' => "person"} |
58 | assert_response :success | 58 | assert_response :success |
59 | assert_select ".search-item", 5 | 59 | assert_select ".search-item", 5 |
60 | assert_template partial: '_person_display' | 60 | assert_template partial: '_person_display' |
61 | end | 61 | end |
62 | 62 | ||
63 | - should 'return results filtered by query with uppercase' do | ||
64 | - get :index, {'query' => "PERSON_1"} | ||
65 | - assert_response :success | ||
66 | - assert_select ".search-item", 1 | ||
67 | - assert_template partial: '_person_display' | ||
68 | - end | 63 | + should 'return results filtered by query with uppercase' do |
64 | + get :index, {'query' => "PERSON 1"} | ||
65 | + assert_response :success | ||
66 | + assert_template partial: '_person_display' | ||
67 | + assert_tag(tag: "div", attributes: { class: "person-item" } , descendant: { tag: "a", child: "person 1"} ) | ||
68 | + end | ||
69 | 69 | ||
70 | - should 'return results filtered by query with downcase' do | ||
71 | - get :index, {'query' => "person_1"} | ||
72 | - assert_response :success | ||
73 | - assert_select ".search-item", 1 | ||
74 | - end | 70 | + should 'return results filtered by query with downcase' do |
71 | + get :index, {'query' => "person 1"} | ||
72 | + assert_response :success | ||
73 | + assert_tag(tag: "div", attributes: { class: "person-item" } , descendant: { tag: "a", child: "person 1"} ) | ||
74 | + end | ||
75 | 75 | ||
76 | should 'return new person indexed' do | 76 | should 'return new person indexed' do |
77 | get :index, { "selected_type" => :community} | 77 | get :index, { "selected_type" => :community} |
78 | assert_response :success | 78 | assert_response :success |
79 | assert_select ".search-item", 6 | 79 | assert_select ".search-item", 6 |
80 | 80 | ||
81 | - fast_create Community, name: "community_#{7}", created_at: Date.new | 81 | + fast_create Community, name: "community #{7}", created_at: Date.new |
82 | Community.import | 82 | Community.import |
83 | sleep 2 | 83 | sleep 2 |
84 | 84 | ||
@@ -108,7 +108,7 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | @@ -108,7 +108,7 @@ class ElasticsearchPluginControllerTest < ActionController::TestCase | ||
108 | end | 108 | end |
109 | 109 | ||
110 | should 'pass params to elastic search controller' do | 110 | should 'pass params to elastic search controller' do |
111 | - get 'index', { query: 'community_' } | 111 | + get 'index', { query: 'community' } |
112 | assert_not_nil assigns(:results) | 112 | assert_not_nil assigns(:results) |
113 | assert_template partial: '_community_display' | 113 | assert_template partial: '_community_display' |
114 | end | 114 | end |
plugins/elasticsearch/test/unit/helpers/elasticsearch_helper_test.rb
0 → 100644
@@ -0,0 +1,86 @@ | @@ -0,0 +1,86 @@ | ||
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 "Joana Abreu" | ||
18 | + create_user "Joao 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 query_string if expression is valid' do | ||
36 | + | ||
37 | + query= "my_query" | ||
38 | + fields = ['name','login'] | ||
39 | + result = query_method(query,fields) | ||
40 | + | ||
41 | + assert_includes result[:query][:query_string][:query], query | ||
42 | + assert_equivalent result[:query][:query_string][:fields], fields | ||
43 | + end | ||
44 | + | ||
45 | + | ||
46 | + should 'return fields from models using weight' do | ||
47 | + class StubClass | ||
48 | + SEARCHABLE_FIELDS = {:name => {:weight => 10}, | ||
49 | + :login => {:weight => 20}, | ||
50 | + :description => {:weight => 2}} | ||
51 | + end | ||
52 | + | ||
53 | + expected = ["name^10", "login^20", "description^2"] | ||
54 | + assert_equivalent expected, fields_from_models([StubClass]) | ||
55 | + end | ||
56 | + | ||
57 | + should 'search from model Person sorted by Alphabetic' do | ||
58 | + self.params= {:selected_type => 'person', | ||
59 | + :filter => 'lexical', | ||
60 | + :query => "Abreu", | ||
61 | + :per_page => 4} | ||
62 | + | ||
63 | + result = process_results | ||
64 | + assert_equal ["Ana Abreu","Joana Abreu","Joao Abreu","Jose Abreu"], result.map(&:name) | ||
65 | + end | ||
66 | + | ||
67 | + should 'search from model Person sorted by More Recent' do | ||
68 | + self.params= {:selected_type => 'person', | ||
69 | + :filter => 'more_recent', | ||
70 | + :query => 'ABREU', | ||
71 | + :per_page => 4} | ||
72 | + | ||
73 | + result = process_results | ||
74 | + assert_equal ["Ana Abreu","Joao Abreu","Joana Abreu","Jose Abreu"], result.map(&:name) | ||
75 | + end | ||
76 | + | ||
77 | + should 'search from model Person sorted by Relevance' do | ||
78 | + self.params= {:selected_type => 'person', | ||
79 | + :query => 'JOA BREU', | ||
80 | + :per_page => 4} | ||
81 | + | ||
82 | + result = process_results | ||
83 | + assert_equal ["Joana Abreu", "Joao Abreu"], result.map(&:name) | ||
84 | + end | ||
85 | + | ||
86 | +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
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | <%= profile_image person %> | 3 | <%= profile_image person %> |
4 | </div> | 4 | </div> |
5 | <div class="right-side"> | 5 | <div class="right-side"> |
6 | - <%= person.created_at.strftime("%d %B %Y at %H:%M") %> - <%= person.name %> <span class="model-label"><%= _("Person") %></span> | 6 | + <%= person.created_at.strftime("%d %B %Y at %H:%M") %> - <span class="model-label"><%= _("Person") %></span> |
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> |
plugins/elasticsearch/views/elasticsearch_plugin/_text_article_display.html.erb
1 | <div class="text_article-header"> | 1 | <div class="text_article-header"> |
2 | - <%= text_article.created_at.strftime("%d %B %Y at %H:%M") %> - <%= text_article.setting[:author_name] %> - <span class="model-label"><%= _("Community") %></span> | 2 | + <%= text_article.created_at.strftime("%d %B %Y at %H:%M") %> - <%= "#{text_article.author.name} -" if text_article.author %> <span class="model-label"><%= _("Article") %></span> |
3 | </div> | 3 | </div> |
4 | <div class="body"> | 4 | <div class="body"> |
5 | <h2><%= link_to text_article.name, text_article.url %></h2> | 5 | <h2><%= link_to text_article.name, text_article.url %></h2> |
plugins/elasticsearch/views/elasticsearch_plugin/_uploaded_file_display.html.erb
1 | <div class="uploaded_file-header"> | 1 | <div class="uploaded_file-header"> |
2 | - <%= uploaded_file.created_at.strftime("%d %B %Y at %H:%M") %> - <%=uploaded_file.setting[:author_name]%> - <span class="model-label"><%= _("Files") %></span> | 2 | + <%= uploaded_file.created_at.strftime("%d %B %Y at %H:%M") %> - <%= "#{uploaded_file.author.name} -" if uploaded_file.author %><span class="model-label"><%= _("Files") %></span> |
3 | </div> | 3 | </div> |
4 | <div class="body"> | 4 | <div class="body"> |
5 | <h2><%= link_to uploaded_file.name, uploaded_file.url %></h2> | 5 | <h2><%= link_to uploaded_file.name, uploaded_file.url %></h2> |
plugins/elasticsearch/views/elasticsearch_plugin/search.html.erb
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | <ul> | 5 | <ul> |
6 | <% for type,value in @searchable_types %> | 6 | <% for type,value in @searchable_types %> |
7 | <li class="select-search-type <%= "active" if type == @selected_type %>"> | 7 | <li class="select-search-type <%= "active" if type == @selected_type %>"> |
8 | - <%= link_to value[:label], "?selected_type=#{type}&query=#{@query}&selected_filter_field=#{@selected_filter_field}"%> | 8 | + <%= link_to value[:label], "?selected_type=#{type}&query=#{@query}&filter=#{@selected_filter}"%> |
9 | </li> | 9 | </li> |
10 | <% end %> | 10 | <% end %> |
11 | </ul> | 11 | </ul> |
@@ -13,8 +13,10 @@ | @@ -13,8 +13,10 @@ | ||
13 | <div class="search-filter"> | 13 | <div class="search-filter"> |
14 | <h3 class="box-title"><%= _("Sort by") %></h3> | 14 | <h3 class="box-title"><%= _("Sort by") %></h3> |
15 | <ul> | 15 | <ul> |
16 | - <% for type in @search_filter_types.values %> | ||
17 | - <li><a href="#"><%= type[:label] %></a></li> | 16 | + <% for type, value in @filter_types %> |
17 | + <li class="select-search-type <%= "active" if type == @selected_filter %>"> | ||
18 | + <%= link_to value[:label], "?selected_type=#{@selected_type}&query=#{@query}&filter=#{type}" %> | ||
19 | + </li> | ||
18 | <% end %> | 20 | <% end %> |
19 | </ul> | 21 | </ul> |
20 | </div> | 22 | </div> |
@@ -24,21 +26,22 @@ | @@ -24,21 +26,22 @@ | ||
24 | <div class="search_field"> | 26 | <div class="search_field"> |
25 | <%= form_tag '/plugin/elasticsearch/search', method: :get do %> | 27 | <%= form_tag '/plugin/elasticsearch/search', method: :get do %> |
26 | <%= hidden_field_tag "selected_type", @selected_type %> | 28 | <%= hidden_field_tag "selected_type", @selected_type %> |
27 | - <%= hidden_field_tag "selected_filter_field", @selected_filter_field %> | 29 | + <% if @selected_filter %> |
30 | + <%= hidden_field_tag "filter", @selected_filter %> | ||
31 | + <% end %> | ||
28 | <%= text_field_tag :query, @query %> | 32 | <%= text_field_tag :query, @query %> |
29 | <%= submit_tag _("Send") %> | 33 | <%= submit_tag _("Send") %> |
30 | <% end %> | 34 | <% end %> |
31 | </div> | 35 | </div> |
32 | <div class="results-count"> | 36 | <div class="results-count"> |
33 | - <% if not @query.blank? %> | ||
34 | - <p> | ||
35 | - <strong><%= @results.total %></strong><%= _(" results for ") %><%= @query %> | 37 | + <p> |
38 | + <strong><%= @hits %></strong> | ||
39 | + <% if not @query.blank? %> | ||
40 | + <%= _(" results for ") %><%= @query %> | ||
41 | + <% else %> | ||
42 | + <%= _(" total results") %> | ||
43 | + <% end %> | ||
36 | </p> | 44 | </p> |
37 | - <% else %> | ||
38 | - <p> | ||
39 | - <strong><%= @results.total %></strong><%= _(" total results") %> | ||
40 | - </p> | ||
41 | - <% end %> | ||
42 | </div> | 45 | </div> |
43 | 46 | ||
44 | 47 | ||
@@ -55,7 +58,7 @@ | @@ -55,7 +58,7 @@ | ||
55 | <% end %> | 58 | <% end %> |
56 | <% end %> | 59 | <% end %> |
57 | <div class="search_paginate"> | 60 | <div class="search_paginate"> |
58 | - <%= pagination_links @results %> | 61 | + <%= pagination_links @results if @results.count > 0 %> |
59 | </div> | 62 | </div> |
60 | </div> | 63 | </div> |
61 | </div> | 64 | </div> |