mm_es_search 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. data/.gitignore +4 -0
  2. data/.project +18 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +1 -0
  5. data/lib/mm_es_search/api/facet/abstract_facet.rb +28 -0
  6. data/lib/mm_es_search/api/facet/date_histogram_facet.rb +11 -0
  7. data/lib/mm_es_search/api/facet/filter_facet.rb +9 -0
  8. data/lib/mm_es_search/api/facet/geo_distance_facet.rb +9 -0
  9. data/lib/mm_es_search/api/facet/histogram_facet.rb +9 -0
  10. data/lib/mm_es_search/api/facet/query_facet.rb +9 -0
  11. data/lib/mm_es_search/api/facet/range_facet.rb +36 -0
  12. data/lib/mm_es_search/api/facet/range_facet_row.rb +97 -0
  13. data/lib/mm_es_search/api/facet/range_item.rb +17 -0
  14. data/lib/mm_es_search/api/facet/statistical_facet.rb +33 -0
  15. data/lib/mm_es_search/api/facet/statistical_facet_result.rb +36 -0
  16. data/lib/mm_es_search/api/facet/terms_facet.rb +62 -0
  17. data/lib/mm_es_search/api/facet/terms_facet_row.rb +35 -0
  18. data/lib/mm_es_search/api/facet/terms_stats_facet.rb +9 -0
  19. data/lib/mm_es_search/api/highlight/result_highlight.rb +40 -0
  20. data/lib/mm_es_search/api/query/abstract_filter.rb +15 -0
  21. data/lib/mm_es_search/api/query/abstract_query.rb +48 -0
  22. data/lib/mm_es_search/api/query/and_filter.rb +9 -0
  23. data/lib/mm_es_search/api/query/bool_filter.rb +11 -0
  24. data/lib/mm_es_search/api/query/bool_query.rb +67 -0
  25. data/lib/mm_es_search/api/query/constant_score_query.rb +31 -0
  26. data/lib/mm_es_search/api/query/custom_filters_score_query.rb +52 -0
  27. data/lib/mm_es_search/api/query/custom_score_query.rb +31 -0
  28. data/lib/mm_es_search/api/query/dismax_query.rb +29 -0
  29. data/lib/mm_es_search/api/query/filtered_query.rb +30 -0
  30. data/lib/mm_es_search/api/query/has_child_filter.rb +11 -0
  31. data/lib/mm_es_search/api/query/has_child_query.rb +25 -0
  32. data/lib/mm_es_search/api/query/has_parent_filter.rb +11 -0
  33. data/lib/mm_es_search/api/query/has_parent_query.rb +25 -0
  34. data/lib/mm_es_search/api/query/match_all_filter.rb +11 -0
  35. data/lib/mm_es_search/api/query/match_all_query.rb +19 -0
  36. data/lib/mm_es_search/api/query/nested_filter.rb +22 -0
  37. data/lib/mm_es_search/api/query/nested_query.rb +62 -0
  38. data/lib/mm_es_search/api/query/not_filter.rb +9 -0
  39. data/lib/mm_es_search/api/query/or_filter.rb +9 -0
  40. data/lib/mm_es_search/api/query/prefix_filter.rb +11 -0
  41. data/lib/mm_es_search/api/query/prefix_query.rb +34 -0
  42. data/lib/mm_es_search/api/query/query_filter.rb +28 -0
  43. data/lib/mm_es_search/api/query/query_string_query.rb +37 -0
  44. data/lib/mm_es_search/api/query/range_filter.rb +11 -0
  45. data/lib/mm_es_search/api/query/range_query.rb +57 -0
  46. data/lib/mm_es_search/api/query/scored_filter.rb +29 -0
  47. data/lib/mm_es_search/api/query/single_bool_filter.rb +66 -0
  48. data/lib/mm_es_search/api/query/term_filter.rb +11 -0
  49. data/lib/mm_es_search/api/query/term_query.rb +34 -0
  50. data/lib/mm_es_search/api/query/terms_filter.rb +11 -0
  51. data/lib/mm_es_search/api/query/terms_query.rb +58 -0
  52. data/lib/mm_es_search/api/query/text_query.rb +42 -0
  53. data/lib/mm_es_search/api/query/top_children_query.rb +28 -0
  54. data/lib/mm_es_search/api/sort/root_sort.rb +36 -0
  55. data/lib/mm_es_search/models/abstract_facet_model.rb +23 -0
  56. data/lib/mm_es_search/models/abstract_query_model.rb +21 -0
  57. data/lib/mm_es_search/models/abstract_range_facet_model.rb +365 -0
  58. data/lib/mm_es_search/models/abstract_search_model.OLD +538 -0
  59. data/lib/mm_es_search/models/abstract_search_model.rb +521 -0
  60. data/lib/mm_es_search/models/abstract_sort_model.rb +13 -0
  61. data/lib/mm_es_search/models/abstract_terms_facet_model.rb +87 -0
  62. data/lib/mm_es_search/models/root_sort_model.rb +20 -0
  63. data/lib/mm_es_search/models/virtual_field_sort.rb +52 -0
  64. data/lib/mm_es_search/utils/facet_row_utils.rb +86 -0
  65. data/lib/mm_es_search/utils/search_logger.rb +10 -0
  66. data/lib/mm_es_search/version.rb +3 -0
  67. data/lib/mm_es_search.rb +124 -0
  68. data/mm_es_search.gemspec +24 -0
  69. metadata +132 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.project ADDED
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>mm_es_search</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>org.radrails.rails.core.railsnature</nature>
16
+ <nature>com.aptana.ruby.core.rubynature</nature>
17
+ </natures>
18
+ </projectDescription>
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mm_es_search.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class AbstractFacet
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ include MmEsSearch::Api::Query
9
+ plugin MmUsesNoId
10
+
11
+ key :label, String
12
+ key :nested, String
13
+ key :scope, String
14
+ one :facet_filter, :class_name => 'MmEsSearch::Api::Query::AbstractQuery'
15
+
16
+ def to_es_query
17
+ facet_params = {}
18
+ facet_params.merge!(:scope => scope) if scope?
19
+ facet_params.merge!(:nested => nested) if nested?
20
+ facet_params.merge!(:facet_filter => facet_filter.to_es_query) if facet_filter?
21
+ return facet_params
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class DateHistogramFacet < AbstractFacet
6
+
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class RangeFacet < AbstractFacet
6
+
7
+ key :field, String
8
+ many :ranges, :class_name => 'MmEsSearch::Api::Facet::RangeItem'
9
+ key :key_field, String
10
+ key :value_field, String
11
+ key :key_script, String
12
+ key :value_script, String
13
+ key :params, Hash
14
+
15
+ def to_es_query
16
+
17
+ range_params = {}
18
+ range_params.merge!(:field => field) if field?
19
+ range_params.merge!(:ranges => ranges.map(&:attributes))
20
+ range_params.merge!(:key_field => size) if key_field?
21
+ range_params.merge!(:value_field => size) if value_field?
22
+ range_params.merge!(:key_script => size) if key_script?
23
+ range_params.merge!(:value_script => size) if value_script?
24
+ range_params.merge!(:params => params) unless params.empty?
25
+
26
+ facet_params = {:range => range_params}.merge(super)
27
+
28
+ return {label => facet_params}
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,97 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class RangeFacetRow
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ include ActionView::Helpers::NumberHelper
9
+ plugin MmUsesUuid
10
+
11
+ key :from
12
+ key :to
13
+ key :count, Integer
14
+ key :min
15
+ key :max
16
+ key :total_count, Integer
17
+ key :total
18
+ key :mean
19
+
20
+ key :checked, String
21
+
22
+ def from=(val)
23
+ super.tap do
24
+ binding.pry if from.is_a?(DateTime)
25
+ end
26
+ end
27
+
28
+ def attributes(*args)
29
+ attr = super
30
+ attr.each_with_object({}) do |(key, value), hsh|
31
+ hsh[key] = case value
32
+ when ActiveSupport::TimeWithZone
33
+ value.utc.to_time
34
+ else
35
+ value
36
+ end
37
+ end
38
+ end
39
+ alias :to_mongo :attributes
40
+
41
+ def zero_count
42
+ self.count = 0
43
+ end
44
+
45
+ def to_range_item
46
+ RangeItem.new(
47
+ :from => from,
48
+ :to => to
49
+ )
50
+ end
51
+
52
+ def to_english(pretty_print = true)
53
+ case from || to
54
+ when Numeric
55
+ render_numeric(pretty_print)
56
+ when Time, DateTime
57
+ end
58
+ end
59
+
60
+ def render_numeric(pretty_print)
61
+
62
+ if pretty_print
63
+ #TODO handle units (see http://bit.ly/rhx05t)
64
+ from_formatted = number_to_human(from) if from?
65
+ to_formatted = number_to_human(to) if to?
66
+ else
67
+ from_formatted = from if from?
68
+ to_formatted = to if to?
69
+ end
70
+
71
+ if from? and to?
72
+ "from #{from_formatted} to #{to_formatted}"
73
+ elsif from?
74
+ "#{from_formatted} or greater"
75
+ else
76
+ "upto #{to_formatted}"
77
+ end
78
+
79
+ end
80
+
81
+ def to_form_name(data_type)
82
+ params = []
83
+ params << "data_type:#{data_type}"
84
+ params << "from:#{from}" if from?
85
+ params << "to:#{to}" if to?
86
+ return params.join('&')
87
+ end
88
+
89
+ def parent
90
+ _parent_document
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,17 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class RangeItem
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ plugin MmUsesNoId
9
+
10
+ key :from
11
+ key :to
12
+
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class StatisticalFacet < AbstractFacet
6
+
7
+ key :field #Array or String
8
+ key :script, String
9
+ key :params, Hash
10
+
11
+ def to_es_query
12
+
13
+ stat_params = if script
14
+ script_params = {:script => script}
15
+ script_params.merge!({:params => params}) if params?
16
+ script_params
17
+ elsif field.is_a?(Array)
18
+ {:fields => field}
19
+ else
20
+ {:field => field}
21
+ end
22
+
23
+ facet_params = {:statistical => stat_params}.merge(super)
24
+
25
+ return {label => facet_params}
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class StatisticalFacetResult
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ plugin MmUsesNoId
9
+
10
+ key :count, Integer
11
+ key :total
12
+ key :sum_of_squares
13
+ key :mean
14
+ key :min
15
+ key :max
16
+ key :variance
17
+ key :std_deviation
18
+
19
+ def attributes(*args)
20
+ attr = super
21
+ attr.each_with_object({}) do |(key, value), hsh|
22
+ hsh[key] = case value
23
+ when ActiveSupport::TimeWithZone
24
+ value.utc.to_time
25
+ else
26
+ value
27
+ end
28
+ end
29
+ end
30
+ alias :to_mongo :attributes
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,62 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class TermsFacet < AbstractFacet
6
+
7
+ key :field #Array or String
8
+ key :path, String
9
+
10
+ key :size, Integer
11
+ key :order, String
12
+ key :exclude, Array #of Strings
13
+
14
+ key :script_field, String
15
+
16
+ key :regex, String
17
+ key :regex_flags, String
18
+
19
+ key :script, String
20
+ key :params, Hash
21
+
22
+ def qualified_field(field_name)
23
+ if path.present?
24
+ [path, field_name].join(".")
25
+ else
26
+ field_name
27
+ end
28
+ end
29
+
30
+ def to_es_query
31
+
32
+ mod_field = case field
33
+ when Array
34
+ field.map { |fname| qualified_field(fname) }
35
+ when String
36
+ qualified_field(field)
37
+ end
38
+
39
+ term_params = {}
40
+ term_params.merge!(:field => mod_field) if field.is_a?(String)
41
+ term_params.merge!(:fields => mod_field) if field.is_a?(Array)
42
+ term_params.merge!(:size => size) if (size? and size != 10)
43
+ term_params.merge!(:order => order) if (order? and order != "count")
44
+ term_params.merge!(:exclude => exclude) unless exclude.empty?
45
+ term_params.merge!(:script_field => script_field) if script_field?
46
+ term_params.merge!(:regex => regex) if regex?
47
+ term_params.merge!(:regex_flags => script_field) if regex_flags?
48
+ term_params.merge!(:script => script) if script?
49
+ term_params.merge!(:params => params) unless params.empty?
50
+
51
+ facet_params = {:terms => term_params}.merge(super)
52
+
53
+ return {label => facet_params}
54
+
55
+ end
56
+
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+ class TermsFacetRow
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ plugin MmUsesUuid
9
+
10
+ key :term, String
11
+ key :count, Integer
12
+
13
+ key :checked, String
14
+
15
+ def zero_count
16
+ self.count = 0
17
+ end
18
+
19
+ def to_english(pretty_print = true)
20
+ StringUtils.label_from_URI(term)
21
+ end
22
+
23
+ def to_form_name(data_type)
24
+ term
25
+ end
26
+
27
+ def parent
28
+ _parent_document
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Facet
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Highlight
4
+
5
+ class ResultHighlight
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ plugin MmUsesNoId
9
+
10
+ many :fields, :class_name => 'MmEsSearch::Api::Highlight::ResultHighlight'
11
+ key :field, String
12
+ key :tag_schema, String
13
+ key :pre_tags, Array
14
+ key :post_tags, Array
15
+ key :fragment_size, Integer
16
+ key :number_of_fragments, Integer
17
+ key :order, String
18
+
19
+ def to_mongo_query
20
+
21
+ raise "to_mongo_query not implemented for ResultHighlight"
22
+
23
+ end
24
+
25
+ def to_es_query
26
+
27
+ highlight_params = self.attributes.except("fields", "pre_tags", "post_tags")
28
+ highlight_params.merge!(:fields => fields.map(&:to_es_query)) unless fields.empty?
29
+ highlight_params.merge!(:pre_tags => pre_tags) unless pre_tags.empty?
30
+ highlight_params.merge!(:post_tags => post_tags) unless post_tags.empty?
31
+
32
+ return field? ? {field => highlight_params.except('field')} : highlight_params
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ module AbstractFilter
6
+ extend ActiveSupport::Concern
7
+
8
+ def to_filter
9
+ self
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ class AbstractQuery
6
+
7
+ include MongoMapper::EmbeddedDocument
8
+ plugin MmUsesNoId
9
+
10
+ def to_filter
11
+ QueryFilter.new(query: self)
12
+ end
13
+
14
+ def es_abs_field
15
+ if path?
16
+ mod_path, indx = path_and_index
17
+ return [mod_path, field].join('.')
18
+ else
19
+ return field
20
+ end
21
+ #TODO make sure we don't need to prefix path anymore - looks like we do if same name used at diff nesting levels, so always include to be safe
22
+ end
23
+
24
+ def mongo_abs_field
25
+ mod_path, array_index = path_and_index
26
+ return array_index.nil? ? field : [path, field].join('.')
27
+ end
28
+
29
+ def path_and_index
30
+
31
+ case path
32
+ when /(?<=\.)[0-9]+$/
33
+ mod_path = path.gsub(/\.[0-9]+/,'')
34
+ array_index = path.split('.').last.to_i
35
+ else
36
+ mod_path = path
37
+ array_index = nil
38
+ end
39
+
40
+ return mod_path, array_index
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ class AndFilter < SingleBoolFilter; end
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ class BoolFilter < BoolQuery
6
+ plugin AbstractFilter
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ class BoolQuery < AbstractQuery
6
+
7
+ many :musts, :class_name => 'MmEsSearch::Api::Query::AbstractQuery'
8
+ many :shoulds, :class_name => 'MmEsSearch::Api::Query::AbstractQuery'
9
+ many :must_nots, :class_name => 'MmEsSearch::Api::Query::AbstractQuery'
10
+ key :boost, Float
11
+ key :minimum_number_should_match, Integer
12
+
13
+ def validate
14
+ raise "cannot have a must_not by itself in a BoolQuery" if (musts.empty? and shoulds.empty? and not self.is_a?(BoolFilter))
15
+ end
16
+
17
+ def to_mongo_query(options = {})
18
+
19
+ validate
20
+
21
+ negated_options = options.merge({:negated => !options[:negated]})
22
+
23
+ and_array = musts.map {|query| query.to_mongo_query(options)} + must_nots.map {|query| query.to_mongo_query(negated_options)}
24
+ or_array = shoulds.map {|query| query.to_mongo_query(options)}
25
+
26
+ bool_params = {}
27
+ bool_params.merge!({'$and' => and_array}) unless and_array.empty?
28
+ bool_params.merge!({'$or' => or_array}) unless or_array.empty?
29
+
30
+ return bool_params
31
+
32
+ end
33
+
34
+ def to_es_query
35
+
36
+ validate
37
+
38
+ # use more optimal and, or, not SingleBoolFilter if appropriate
39
+ if self.is_a?(BoolFilter)
40
+ if (shoulds + must_nots).empty? and not musts.empty? and boost.nil?
41
+ return AndFilter.new(:filters => musts).to_es_query
42
+ elsif (musts + must_nots).empty? and not shoulds.empty? and boost.nil? and minimum_number_should_match == 1
43
+ return OrFilter.new(:filters => shoulds).to_es_query
44
+ elsif (musts + shoulds).empty? and not must_nots.empty? and boost.nil?
45
+ return NotFilter.new(:filters => must_nots).to_es_query
46
+ end
47
+ end
48
+
49
+ must_array = musts.map {|query| query.to_es_query}
50
+ should_array = shoulds.map {|query| query.to_es_query}
51
+ must_not_array = must_nots.map {|query| query.to_es_query}
52
+
53
+ bool_params = {}
54
+ bool_params.merge!({:must => must_array}) unless must_array.empty?
55
+ bool_params.merge!({:should => should_array}) unless should_array.empty?
56
+ bool_params.merge!({:must_not => must_not_array}) unless must_not_array.empty?
57
+ bool_params.merge!({:boost => boost}) unless boost.nil?
58
+ bool_params.merge!({:minimum_number_should_match => minimum_number_should_match}) if minimum_number_should_match?
59
+ return {:bool => bool_params}
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,31 @@
1
+ module MmEsSearch
2
+ module Api
3
+ module Query
4
+
5
+ class ConstantScoreQuery < AbstractQuery
6
+
7
+ one :query, :class_name => 'MmEsSearch::Api::Query::AbstractQuery'
8
+ key :boost, Integer
9
+
10
+ def to_mongo_query(options = {})
11
+
12
+ return query.to_mongo_query(options)
13
+
14
+ end
15
+
16
+ def to_es_query
17
+
18
+ constant_score_params = {
19
+ :query => query.to_es_query
20
+ }
21
+ constant_score_params.merge!(:boost => boost) if boost?
22
+
23
+ return {:constant_score => constant_score_params}
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end