Commit 54c48b92f0ef2d197369c03b6096bb3e19d6713e
1 parent
f915ef75
Exists in
master
and in
8 other branches
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,138 +23,10 @@ module Searchkick | ||
23 | mappings = custom_mapping | 23 | mappings = custom_mapping |
24 | else | 24 | else |
25 | settings = generate_settings | 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 | end | 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 | settings: settings, | 32 | settings: settings, |
@@ -433,6 +305,132 @@ module Searchkick | @@ -433,6 +305,132 @@ module Searchkick | ||
433 | settings | 305 | settings |
434 | end | 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 | def add_synonyms(settings) | 434 | def add_synonyms(settings) |
437 | synonyms = options[:synonyms] || [] | 435 | synonyms = options[:synonyms] || [] |
438 | synonyms = synonyms.call if synonyms.respond_to?(:call) | 436 | synonyms = synonyms.call if synonyms.respond_to?(:call) |
@@ -499,6 +497,13 @@ module Searchkick | @@ -499,6 +497,13 @@ module Searchkick | ||
499 | end | 497 | end |
500 | end | 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 | def default_type | 507 | def default_type |
503 | "text" | 508 | "text" |
504 | end | 509 | end |