Commit 7c23a765db516a4879c6e0d3566b2fa1c22b0c1c

Authored by David Silva
Committed by Macartur Sousa
1 parent 0dd3b2f8

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 &lt; ApplicationController @@ -18,6 +18,7 @@ class ElasticsearchPluginController &lt; 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 &lt; ApplicationController @@ -26,13 +27,8 @@ class ElasticsearchPluginController &lt; 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 &lt; Noosfero::Plugin @@ -17,12 +17,24 @@ class ElasticsearchPlugin &lt; 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 &#39;../elasticsearch_indexed_model&#39; @@ -3,7 +3,9 @@ require_relative &#39;../elasticsearch_indexed_model&#39;
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
@@ -6,6 +6,7 @@ class Event @@ -6,6 +6,7 @@ class Event
6 { 6 {
7 :advertise => {}, 7 :advertise => {},
8 :published => {}, 8 :published => {},
  9 + :created_at => {type: 'date'}
9 } 10 }
10 end 11 end
11 include ElasticsearchIndexedModel 12 include ElasticsearchIndexedModel
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
@@ -6,6 +6,7 @@ class UploadedFile @@ -6,6 +6,7 @@ class UploadedFile
6 { 6 {
7 :advertise => {}, 7 :advertise => {},
8 :published => {}, 8 :published => {},
  9 + :created_at => {type: 'date'}
9 } 10 }
10 end 11 end
11 include ElasticsearchIndexedModel 12 include ElasticsearchIndexedModel
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 &lt; ActiveSupport::TestCase @@ -9,8 +9,8 @@ class ElasticsearchPluginApiTest &lt; 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 &lt; ActiveSupport::TestCase @@ -28,14 +28,14 @@ class ElasticsearchPluginApiTest &lt; 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 &lt; ActiveSupport::TestCase @@ -47,5 +47,4 @@ class ElasticsearchPluginApiTest &lt; 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 &lt; ActionController::TestCase @@ -15,13 +15,13 @@ class ElasticsearchPluginControllerTest &lt; 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 &lt; ActionController::TestCase @@ -30,8 +30,8 @@ class ElasticsearchPluginControllerTest &lt; 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 &lt; ActionController::TestCase @@ -54,31 +54,31 @@ class ElasticsearchPluginControllerTest &lt; 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 &lt; ActionController::TestCase @@ -108,7 +108,7 @@ class ElasticsearchPluginControllerTest &lt; 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 &lt; ActionController::TestCase @@ -8,10 +8,6 @@ class CommunityTest &lt; 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 &lt; ActionController::TestCase @@ -8,10 +8,6 @@ class EventTest &lt; 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 &lt; ActionController::TestCase @@ -8,10 +8,6 @@ class PersonTest &lt; 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 &lt; ActionController::TestCase @@ -24,5 +20,4 @@ class PersonTest &lt; 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 &lt; ActionController::TestCase @@ -8,10 +8,6 @@ class TextArticleTest &lt; 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 &lt; ActionController::TestCase @@ -8,10 +8,6 @@ class UploadedFileTest &lt; 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>