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