Commit 54c48b92f0ef2d197369c03b6096bb3e19d6713e

Authored by Andrew Kane
1 parent f915ef75

Added generate mappings method

Showing 1 changed file with 135 additions and 130 deletions   Show diff stats
lib/searchkick/index_options.rb
... ... @@ -23,138 +23,10 @@ module Searchkick
23 23 mappings = custom_mapping
24 24 else
25 25 settings = generate_settings
26   -
27   - mapping = {}
28   -
29   - keyword_mapping = {type: "keyword"}
30   - keyword_mapping[:ignore_above] = options[:ignore_above] || 30000
31   -
32   - # conversions
33   - Array(options[:conversions]).each do |conversions_field|
34   - mapping[conversions_field] = {
35   - type: "nested",
36   - properties: {
37   - query: {type: default_type, analyzer: "searchkick_keyword"},
38   - count: {type: "integer"}
39   - }
40   - }
41   - end
42   -
43   - mapping_options = Hash[
44   - [:suggest, :word, :text_start, :text_middle, :text_end, :word_start, :word_middle, :word_end, :highlight, :searchable, :filterable]
45   - .map { |type| [type, (options[type] || []).map(&:to_s)] }
46   - ]
47   -
48   - word = options[:word] != false && (!options[:match] || options[:match] == :word)
49   -
50   - mapping_options[:searchable].delete("_all")
51   -
52   - analyzed_field_options = {type: default_type, index: true, analyzer: default_analyzer}
53   -
54   - mapping_options.values.flatten.uniq.each do |field|
55   - fields = {}
56   -
57   - if options.key?(:filterable) && !mapping_options[:filterable].include?(field)
58   - fields[field] = {type: default_type, index: false}
59   - else
60   - fields[field] = keyword_mapping
61   - end
62   -
63   - if !options[:searchable] || mapping_options[:searchable].include?(field)
64   - if word
65   - fields[:analyzed] = analyzed_field_options
66   -
67   - if mapping_options[:highlight].include?(field)
68   - fields[:analyzed][:term_vector] = "with_positions_offsets"
69   - end
70   - end
71   -
72   - mapping_options.except(:highlight, :searchable, :filterable, :word).each do |type, f|
73   - if options[:match] == type || f.include?(field)
74   - fields[type] = {type: default_type, index: true, analyzer: "searchkick_#{type}_index"}
75   - end
76   - end
77   - end
78   -
79   - mapping[field] = fields[field].merge(fields: fields.except(field))
80   - end
81   -
82   - (options[:locations] || []).map(&:to_s).each do |field|
83   - mapping[field] = {
84   - type: "geo_point"
85   - }
86   - end
87   -
88   - options[:geo_shape] = options[:geo_shape].product([{}]).to_h if options[:geo_shape].is_a?(Array)
89   - (options[:geo_shape] || {}).each do |field, shape_options|
90   - mapping[field] = shape_options.merge(type: "geo_shape")
91   - end
92   -
93   - if options[:inheritance]
94   - mapping[:type] = keyword_mapping
95   - end
96   -
97   - routing = {}
98   - if options[:routing]
99   - routing = {required: true}
100   - unless options[:routing] == true
101   - routing[:path] = options[:routing].to_s
102   - end
103   - end
104   -
105   - dynamic_fields = {
106   - # analyzed field must be the default field for include_in_all
107   - # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
108   - # however, we can include the not_analyzed field in _all
109   - # and the _all index analyzer will take care of it
110   - "{name}" => keyword_mapping
111   - }
112   -
113   - if options.key?(:filterable)
114   - dynamic_fields["{name}"] = {type: default_type, index: false}
115   - end
116   -
117   - unless options[:searchable]
118   - if options[:match] && options[:match] != :word
119   - dynamic_fields[options[:match]] = {type: default_type, index: true, analyzer: "searchkick_#{options[:match]}_index"}
120   - end
121   -
122   - if word
123   - dynamic_fields[:analyzed] = analyzed_field_options
124   - end
125   - end
126   -
127   - # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
128   - multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
129   -
130   - mappings = {
131   - properties: mapping,
132   - _routing: routing,
133   - # https://gist.github.com/kimchy/2898285
134   - dynamic_templates: [
135   - {
136   - string_template: {
137   - match: "*",
138   - match_mapping_type: "string",
139   - mapping: multi_field
140   - }
141   - }
142   - ]
143   - }
144   -
145   - if below70
146   - mappings = {index_type => mappings}
147   - end
148   -
149   - mappings = mappings.symbolize_keys.deep_merge(custom_mapping.symbolize_keys)
  26 + mappings = generate_mappings.symbolize_keys.deep_merge(custom_mapping.symbolize_keys)
150 27 end
151 28  
152   - if options[:deep_paging]
153   - if !settings.dig(:index, :max_result_window) && !settings[:"index.max_result_window"]
154   - settings[:index] ||= {}
155   - settings[:index][:max_result_window] = 1_000_000_000
156   - end
157   - end
  29 + set_deep_paging(settings) if options[:deep_paging]
158 30  
159 31 {
160 32 settings: settings,
... ... @@ -433,6 +305,132 @@ module Searchkick
433 305 settings
434 306 end
435 307  
  308 + def generate_mappings
  309 + mapping = {}
  310 +
  311 + keyword_mapping = {type: "keyword"}
  312 + keyword_mapping[:ignore_above] = options[:ignore_above] || 30000
  313 +
  314 + # conversions
  315 + Array(options[:conversions]).each do |conversions_field|
  316 + mapping[conversions_field] = {
  317 + type: "nested",
  318 + properties: {
  319 + query: {type: default_type, analyzer: "searchkick_keyword"},
  320 + count: {type: "integer"}
  321 + }
  322 + }
  323 + end
  324 +
  325 + mapping_options = Hash[
  326 + [:suggest, :word, :text_start, :text_middle, :text_end, :word_start, :word_middle, :word_end, :highlight, :searchable, :filterable]
  327 + .map { |type| [type, (options[type] || []).map(&:to_s)] }
  328 + ]
  329 +
  330 + word = options[:word] != false && (!options[:match] || options[:match] == :word)
  331 +
  332 + mapping_options[:searchable].delete("_all")
  333 +
  334 + analyzed_field_options = {type: default_type, index: true, analyzer: default_analyzer}
  335 +
  336 + mapping_options.values.flatten.uniq.each do |field|
  337 + fields = {}
  338 +
  339 + if options.key?(:filterable) && !mapping_options[:filterable].include?(field)
  340 + fields[field] = {type: default_type, index: false}
  341 + else
  342 + fields[field] = keyword_mapping
  343 + end
  344 +
  345 + if !options[:searchable] || mapping_options[:searchable].include?(field)
  346 + if word
  347 + fields[:analyzed] = analyzed_field_options
  348 +
  349 + if mapping_options[:highlight].include?(field)
  350 + fields[:analyzed][:term_vector] = "with_positions_offsets"
  351 + end
  352 + end
  353 +
  354 + mapping_options.except(:highlight, :searchable, :filterable, :word).each do |type, f|
  355 + if options[:match] == type || f.include?(field)
  356 + fields[type] = {type: default_type, index: true, analyzer: "searchkick_#{type}_index"}
  357 + end
  358 + end
  359 + end
  360 +
  361 + mapping[field] = fields[field].merge(fields: fields.except(field))
  362 + end
  363 +
  364 + (options[:locations] || []).map(&:to_s).each do |field|
  365 + mapping[field] = {
  366 + type: "geo_point"
  367 + }
  368 + end
  369 +
  370 + options[:geo_shape] = options[:geo_shape].product([{}]).to_h if options[:geo_shape].is_a?(Array)
  371 + (options[:geo_shape] || {}).each do |field, shape_options|
  372 + mapping[field] = shape_options.merge(type: "geo_shape")
  373 + end
  374 +
  375 + if options[:inheritance]
  376 + mapping[:type] = keyword_mapping
  377 + end
  378 +
  379 + routing = {}
  380 + if options[:routing]
  381 + routing = {required: true}
  382 + unless options[:routing] == true
  383 + routing[:path] = options[:routing].to_s
  384 + end
  385 + end
  386 +
  387 + dynamic_fields = {
  388 + # analyzed field must be the default field for include_in_all
  389 + # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
  390 + # however, we can include the not_analyzed field in _all
  391 + # and the _all index analyzer will take care of it
  392 + "{name}" => keyword_mapping
  393 + }
  394 +
  395 + if options.key?(:filterable)
  396 + dynamic_fields["{name}"] = {type: default_type, index: false}
  397 + end
  398 +
  399 + unless options[:searchable]
  400 + if options[:match] && options[:match] != :word
  401 + dynamic_fields[options[:match]] = {type: default_type, index: true, analyzer: "searchkick_#{options[:match]}_index"}
  402 + end
  403 +
  404 + if word
  405 + dynamic_fields[:analyzed] = analyzed_field_options
  406 + end
  407 + end
  408 +
  409 + # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
  410 + multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
  411 +
  412 + mappings = {
  413 + properties: mapping,
  414 + _routing: routing,
  415 + # https://gist.github.com/kimchy/2898285
  416 + dynamic_templates: [
  417 + {
  418 + string_template: {
  419 + match: "*",
  420 + match_mapping_type: "string",
  421 + mapping: multi_field
  422 + }
  423 + }
  424 + ]
  425 + }
  426 +
  427 + if below70
  428 + mappings = {index_type => mappings}
  429 + end
  430 +
  431 + mappings
  432 + end
  433 +
436 434 def add_synonyms(settings)
437 435 synonyms = options[:synonyms] || []
438 436 synonyms = synonyms.call if synonyms.respond_to?(:call)
... ... @@ -499,6 +497,13 @@ module Searchkick
499 497 end
500 498 end
501 499  
  500 + def set_deep_paging(settings)
  501 + if !settings.dig(:index, :max_result_window) && !settings[:"index.max_result_window"]
  502 + settings[:index] ||= {}
  503 + settings[:index][:max_result_window] = 1_000_000_000
  504 + end
  505 + end
  506 +
502 507 def default_type
503 508 "text"
504 509 end
... ...