Commit 7999b2b3341f71b602bc8a044a601c28c9f3cfb4
Exists in
master
and in
21 other branches
Merge branch 'code_refactor' of https://github.com/doubiz/searchkick
Showing
1 changed file
with
266 additions
and
238 deletions
Show diff stats
lib/searchkick/query.rb
@@ -149,28 +149,7 @@ module Searchkick | @@ -149,28 +149,7 @@ module Searchkick | ||
149 | end | 149 | end |
150 | 150 | ||
151 | def prepare | 151 | def prepare |
152 | - boost_fields = {} | ||
153 | - fields = options[:fields] || searchkick_options[:searchable] | ||
154 | - fields = | ||
155 | - if fields | ||
156 | - if options[:autocomplete] | ||
157 | - fields.map { |f| "#{f}.autocomplete" } | ||
158 | - else | ||
159 | - fields.map do |value| | ||
160 | - k, v = value.is_a?(Hash) ? value.to_a.first : [value, options[:match] || searchkick_options[:match] || :word] | ||
161 | - k2, boost = k.to_s.split("^", 2) | ||
162 | - field = "#{k2}.#{v == :word ? 'analyzed' : v}" | ||
163 | - boost_fields[field] = boost.to_f if boost | ||
164 | - field | ||
165 | - end | ||
166 | - end | ||
167 | - else | ||
168 | - if options[:autocomplete] | ||
169 | - (searchkick_options[:autocomplete] || []).map { |f| "#{f}.autocomplete" } | ||
170 | - else | ||
171 | - ["_all"] | ||
172 | - end | ||
173 | - end | 152 | + boost_fields, fields = set_fields |
174 | 153 | ||
175 | operator = options[:operator] || (options[:partial] ? "or" : "and") | 154 | operator = options[:operator] || (options[:partial] ? "or" : "and") |
176 | 155 | ||
@@ -187,7 +166,7 @@ module Searchkick | @@ -187,7 +166,7 @@ module Searchkick | ||
187 | personalize_field = searchkick_options[:personalize] | 166 | personalize_field = searchkick_options[:personalize] |
188 | 167 | ||
189 | all = term == "*" | 168 | all = term == "*" |
190 | - facet_limits = {} | 169 | + |
191 | 170 | ||
192 | options[:json] ||= options[:body] | 171 | options[:json] ||= options[:body] |
193 | if options[:json] | 172 | if options[:json] |
@@ -324,52 +303,11 @@ module Searchkick | @@ -324,52 +303,11 @@ module Searchkick | ||
324 | custom_filters = [] | 303 | custom_filters = [] |
325 | multiply_filters = [] | 304 | multiply_filters = [] |
326 | 305 | ||
327 | - boost_by = options[:boost_by] || {} | 306 | + set_boost_by(multiply_filters, custom_filters) |
328 | 307 | ||
329 | - if boost_by.is_a?(Array) | ||
330 | - boost_by = Hash[boost_by.map { |f| [f, {factor: 1}] }] | ||
331 | - elsif boost_by.is_a?(Hash) | ||
332 | - multiply_by, boost_by = boost_by.partition { |_, v| v[:boost_mode] == "multiply" }.map { |i| Hash[i] } | ||
333 | - end | ||
334 | - boost_by[options[:boost]] = {factor: 1} if options[:boost] | 308 | + set_boost_where(custom_filters, personalize_field) |
335 | 309 | ||
336 | - custom_filters.concat boost_filters(boost_by, log: true) | ||
337 | - multiply_filters.concat boost_filters(multiply_by || {}) | ||
338 | - | ||
339 | - boost_where = options[:boost_where] || {} | ||
340 | - if options[:user_id] && personalize_field | ||
341 | - boost_where[personalize_field] = options[:user_id] | ||
342 | - end | ||
343 | - if options[:personalize] | ||
344 | - boost_where = boost_where.merge(options[:personalize]) | ||
345 | - end | ||
346 | - boost_where.each do |field, value| | ||
347 | - if value.is_a?(Array) && value.first.is_a?(Hash) | ||
348 | - value.each do |value_factor| | ||
349 | - custom_filters << custom_filter(field, value_factor[:value], value_factor[:factor]) | ||
350 | - end | ||
351 | - elsif value.is_a?(Hash) | ||
352 | - custom_filters << custom_filter(field, value[:value], value[:factor]) | ||
353 | - else | ||
354 | - factor = 1000 | ||
355 | - custom_filters << custom_filter(field, value, factor) | ||
356 | - end | ||
357 | - end | ||
358 | - | ||
359 | - boost_by_distance = options[:boost_by_distance] | ||
360 | - if boost_by_distance | ||
361 | - boost_by_distance = {function: :gauss, scale: "5mi"}.merge(boost_by_distance) | ||
362 | - if !boost_by_distance[:field] || !boost_by_distance[:origin] | ||
363 | - raise ArgumentError, "boost_by_distance requires :field and :origin" | ||
364 | - end | ||
365 | - function_params = boost_by_distance.select { |k, _| [:origin, :scale, :offset, :decay].include?(k) } | ||
366 | - function_params[:origin] = location_value(function_params[:origin]) | ||
367 | - custom_filters << { | ||
368 | - boost_by_distance[:function] => { | ||
369 | - boost_by_distance[:field] => function_params | ||
370 | - } | ||
371 | - } | ||
372 | - end | 310 | + set_boost_by_distance(custom_filters) if options[:boost_by_distance] |
373 | 311 | ||
374 | if custom_filters.any? | 312 | if custom_filters.any? |
375 | payload = { | 313 | payload = { |
@@ -399,187 +337,24 @@ module Searchkick | @@ -399,187 +337,24 @@ module Searchkick | ||
399 | payload[:explain] = options[:explain] if options[:explain] | 337 | payload[:explain] = options[:explain] if options[:explain] |
400 | 338 | ||
401 | # order | 339 | # order |
402 | - if options[:order] | ||
403 | - order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc} | ||
404 | - # TODO id transformation for arrays | ||
405 | - payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? :_id : k, v] }] | ||
406 | - end | 340 | + set_order(payload) if options[:order] |
407 | 341 | ||
408 | # filters | 342 | # filters |
409 | filters = where_filters(options[:where]) | 343 | filters = where_filters(options[:where]) |
410 | - if filters.any? | ||
411 | - if options[:facets] || options[:aggs] | ||
412 | - payload[:filter] = { | ||
413 | - and: filters | ||
414 | - } | ||
415 | - else | ||
416 | - # more efficient query if no facets | ||
417 | - payload[:query] = { | ||
418 | - filtered: { | ||
419 | - query: payload[:query], | ||
420 | - filter: { | ||
421 | - and: filters | ||
422 | - } | ||
423 | - } | ||
424 | - } | ||
425 | - end | ||
426 | - end | 344 | + set_filters(payload, filters) if filters.any? |
427 | 345 | ||
428 | # facets | 346 | # facets |
429 | - if options[:facets] | ||
430 | - facets = options[:facets] || {} | ||
431 | - facets = Hash[facets.map { |f| [f, {}] }] if facets.is_a?(Array) # convert to more advanced syntax | ||
432 | - | ||
433 | - payload[:facets] = {} | ||
434 | - facets.each do |field, facet_options| | ||
435 | - # ask for extra facets due to | ||
436 | - # https://github.com/elasticsearch/elasticsearch/issues/1305 | ||
437 | - size = facet_options[:limit] ? facet_options[:limit] + 150 : 1_000 | ||
438 | - | ||
439 | - if facet_options[:ranges] | ||
440 | - payload[:facets][field] = { | ||
441 | - range: { | ||
442 | - field.to_sym => facet_options[:ranges] | ||
443 | - } | ||
444 | - } | ||
445 | - elsif facet_options[:stats] | ||
446 | - payload[:facets][field] = { | ||
447 | - terms_stats: { | ||
448 | - key_field: field, | ||
449 | - value_script: below14? ? "doc.score" : "_score", | ||
450 | - size: size | ||
451 | - } | ||
452 | - } | ||
453 | - else | ||
454 | - payload[:facets][field] = { | ||
455 | - terms: { | ||
456 | - field: facet_options[:field] || field, | ||
457 | - size: size | ||
458 | - } | ||
459 | - } | ||
460 | - end | ||
461 | - | ||
462 | - facet_limits[field] = facet_options[:limit] if facet_options[:limit] | ||
463 | - | ||
464 | - # offset is not possible | ||
465 | - # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html | ||
466 | - | ||
467 | - facet_options.deep_merge!(where: options.fetch(:where, {}).reject { |k| k == field }) if options[:smart_facets] == true | ||
468 | - facet_filters = where_filters(facet_options[:where]) | ||
469 | - if facet_filters.any? | ||
470 | - payload[:facets][field][:facet_filter] = { | ||
471 | - and: { | ||
472 | - filters: facet_filters | ||
473 | - } | ||
474 | - } | ||
475 | - end | ||
476 | - end | ||
477 | - end | 347 | + set_facets(payload) if options[:facets] |
478 | 348 | ||
479 | # aggregations | 349 | # aggregations |
480 | - if options[:aggs] | ||
481 | - aggs = options[:aggs] | ||
482 | - payload[:aggs] = {} | ||
483 | - | ||
484 | - aggs = Hash[aggs.map { |f| [f, {}] }] if aggs.is_a?(Array) # convert to more advanced syntax | ||
485 | - | ||
486 | - aggs.each do |field, agg_options| | ||
487 | - size = agg_options[:limit] ? agg_options[:limit] : 1_000 | ||
488 | - shared_agg_options = agg_options.slice(:order) | ||
489 | - | ||
490 | - if agg_options[:ranges] | ||
491 | - payload[:aggs][field] = { | ||
492 | - range: { | ||
493 | - field: agg_options[:field] || field, | ||
494 | - ranges: agg_options[:ranges] | ||
495 | - }.merge(shared_agg_options) | ||
496 | - } | ||
497 | - elsif agg_options[:date_ranges] | ||
498 | - payload[:aggs][field] = { | ||
499 | - date_range: { | ||
500 | - field: agg_options[:field] || field, | ||
501 | - ranges: agg_options[:date_ranges] | ||
502 | - }.merge(shared_agg_options) | ||
503 | - } | ||
504 | - else | ||
505 | - payload[:aggs][field] = { | ||
506 | - terms: { | ||
507 | - field: agg_options[:field] || field, | ||
508 | - size: size | ||
509 | - }.merge(shared_agg_options) | ||
510 | - } | ||
511 | - end | ||
512 | - | ||
513 | - where = {} | ||
514 | - where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false | ||
515 | - agg_filters = where_filters(where.merge(agg_options[:where] || {})) | ||
516 | - if agg_filters.any? | ||
517 | - payload[:aggs][field] = { | ||
518 | - filter: { | ||
519 | - bool: { | ||
520 | - must: agg_filters | ||
521 | - } | ||
522 | - }, | ||
523 | - aggs: { | ||
524 | - field => payload[:aggs][field] | ||
525 | - } | ||
526 | - } | ||
527 | - end | ||
528 | - end | ||
529 | - end | ||
530 | - | 350 | + set_aggregations(payload) if options[:aggs] |
351 | + | ||
531 | # suggestions | 352 | # suggestions |
532 | - if options[:suggest] | ||
533 | - suggest_fields = (searchkick_options[:suggest] || []).map(&:to_s) | ||
534 | - | ||
535 | - # intersection | ||
536 | - if options[:fields] | ||
537 | - suggest_fields &= options[:fields].map { |v| (v.is_a?(Hash) ? v.keys.first : v).to_s.split("^", 2).first } | ||
538 | - end | ||
539 | - | ||
540 | - if suggest_fields.any? | ||
541 | - payload[:suggest] = {text: term} | ||
542 | - suggest_fields.each do |field| | ||
543 | - payload[:suggest][field] = { | ||
544 | - phrase: { | ||
545 | - field: "#{field}.suggest" | ||
546 | - } | ||
547 | - } | ||
548 | - end | ||
549 | - end | ||
550 | - end | 353 | + set_suggestions(payload) if options[:suggest] |
551 | 354 | ||
552 | # highlight | 355 | # highlight |
553 | - if options[:highlight] | ||
554 | - payload[:highlight] = { | ||
555 | - fields: Hash[fields.map { |f| [f, {}] }] | ||
556 | - } | 356 | + set_highlights(payload, fields) if options[:highlight] |
557 | 357 | ||
558 | - if options[:highlight].is_a?(Hash) | ||
559 | - if (tag = options[:highlight][:tag]) | ||
560 | - payload[:highlight][:pre_tags] = [tag] | ||
561 | - payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")] | ||
562 | - end | ||
563 | - | ||
564 | - if (fragment_size = options[:highlight][:fragment_size]) | ||
565 | - payload[:highlight][:fragment_size] = fragment_size | ||
566 | - end | ||
567 | - if (encoder = options[:highlight][:encoder]) | ||
568 | - payload[:highlight][:encoder] = encoder | ||
569 | - end | ||
570 | - | ||
571 | - highlight_fields = options[:highlight][:fields] | ||
572 | - if highlight_fields | ||
573 | - payload[:highlight][:fields] = {} | ||
574 | - | ||
575 | - highlight_fields.each do |name, opts| | ||
576 | - payload[:highlight][:fields]["#{name}.#{@match_suffix}"] = opts || {} | ||
577 | - end | ||
578 | - end | ||
579 | - end | ||
580 | - | ||
581 | - @highlighted_fields = payload[:highlight][:fields].keys | ||
582 | - end | ||
583 | 358 | ||
584 | # An empty array will cause only the _id and _type for each hit to be returned | 359 | # An empty array will cause only the _id and _type for each hit to be returned |
585 | # doc for :select - http://www.elasticsearch.org/guide/reference/api/search/fields/ | 360 | # doc for :select - http://www.elasticsearch.org/guide/reference/api/search/fields/ |
@@ -606,13 +381,266 @@ module Searchkick | @@ -606,13 +381,266 @@ module Searchkick | ||
606 | end | 381 | end |
607 | 382 | ||
608 | @body = payload | 383 | @body = payload |
609 | - @facet_limits = facet_limits | 384 | + @facet_limits = @facet_limits || {} |
610 | @page = page | 385 | @page = page |
611 | @per_page = per_page | 386 | @per_page = per_page |
612 | @padding = padding | 387 | @padding = padding |
613 | @load = load | 388 | @load = load |
614 | end | 389 | end |
615 | 390 | ||
391 | + def set_fields | ||
392 | + boost_fields = {} | ||
393 | + fields = options[:fields] || searchkick_options[:searchable] | ||
394 | + fields = | ||
395 | + if fields | ||
396 | + if options[:autocomplete] | ||
397 | + fields.map { |f| "#{f}.autocomplete" } | ||
398 | + else | ||
399 | + fields.map do |value| | ||
400 | + k, v = value.is_a?(Hash) ? value.to_a.first : [value, options[:match] || searchkick_options[:match] || :word] | ||
401 | + k2, boost = k.to_s.split("^", 2) | ||
402 | + field = "#{k2}.#{v == :word ? 'analyzed' : v}" | ||
403 | + boost_fields[field] = boost.to_f if boost | ||
404 | + field | ||
405 | + end | ||
406 | + end | ||
407 | + else | ||
408 | + if options[:autocomplete] | ||
409 | + (searchkick_options[:autocomplete] || []).map { |f| "#{f}.autocomplete" } | ||
410 | + else | ||
411 | + ["_all"] | ||
412 | + end | ||
413 | + end | ||
414 | + [boost_fields, fields] | ||
415 | + end | ||
416 | + | ||
417 | + def set_boost_by_distance(custom_filters) | ||
418 | + boost_by_distance = options[:boost_by_distance] || {} | ||
419 | + boost_by_distance = {function: :gauss, scale: "5mi"}.merge(boost_by_distance) | ||
420 | + if !boost_by_distance[:field] || !boost_by_distance[:origin] | ||
421 | + raise ArgumentError, "boost_by_distance requires :field and :origin" | ||
422 | + end | ||
423 | + function_params = boost_by_distance.select { |k, _| [:origin, :scale, :offset, :decay].include?(k) } | ||
424 | + function_params[:origin] = location_value(function_params[:origin]) | ||
425 | + custom_filters << { | ||
426 | + boost_by_distance[:function] => { | ||
427 | + boost_by_distance[:field] => function_params | ||
428 | + } | ||
429 | + } | ||
430 | + end | ||
431 | + | ||
432 | + def set_boost_by(multiply_filters, custom_filters) | ||
433 | + boost_by = options[:boost_by] || {} | ||
434 | + if boost_by.is_a?(Array) | ||
435 | + boost_by = Hash[boost_by.map { |f| [f, {factor: 1}] }] | ||
436 | + elsif boost_by.is_a?(Hash) | ||
437 | + multiply_by, boost_by = boost_by.partition { |_, v| v[:boost_mode] == "multiply" }.map { |i| Hash[i] } | ||
438 | + end | ||
439 | + boost_by[options[:boost]] = {factor: 1} if options[:boost] | ||
440 | + | ||
441 | + custom_filters.concat boost_filters(boost_by, log: true) | ||
442 | + multiply_filters.concat boost_filters(multiply_by || {}) | ||
443 | + end | ||
444 | + | ||
445 | + def set_boost_where(custom_filters, personalize_field) | ||
446 | + boost_where = options[:boost_where] || {} | ||
447 | + if options[:user_id] && personalize_field | ||
448 | + boost_where[personalize_field] = options[:user_id] | ||
449 | + end | ||
450 | + if options[:personalize] | ||
451 | + boost_where = boost_where.merge(options[:personalize]) | ||
452 | + end | ||
453 | + boost_where.each do |field, value| | ||
454 | + if value.is_a?(Array) && value.first.is_a?(Hash) | ||
455 | + value.each do |value_factor| | ||
456 | + custom_filters << custom_filter(field, value_factor[:value], value_factor[:factor]) | ||
457 | + end | ||
458 | + elsif value.is_a?(Hash) | ||
459 | + custom_filters << custom_filter(field, value[:value], value[:factor]) | ||
460 | + else | ||
461 | + factor = 1000 | ||
462 | + custom_filters << custom_filter(field, value, factor) | ||
463 | + end | ||
464 | + end | ||
465 | + end | ||
466 | + | ||
467 | + def set_suggestions(payload) | ||
468 | + suggest_fields = (searchkick_options[:suggest] || []).map(&:to_s) | ||
469 | + | ||
470 | + # intersection | ||
471 | + if options[:fields] | ||
472 | + suggest_fields &= options[:fields].map { |v| (v.is_a?(Hash) ? v.keys.first : v).to_s.split("^", 2).first } | ||
473 | + end | ||
474 | + | ||
475 | + if suggest_fields.any? | ||
476 | + payload[:suggest] = {text: term} | ||
477 | + suggest_fields.each do |field| | ||
478 | + payload[:suggest][field] = { | ||
479 | + phrase: { | ||
480 | + field: "#{field}.suggest" | ||
481 | + } | ||
482 | + } | ||
483 | + end | ||
484 | + end | ||
485 | + end | ||
486 | + | ||
487 | + def set_highlights(payload, fields) | ||
488 | + payload[:highlight] = { | ||
489 | + fields: Hash[fields.map { |f| [f, {}] }] | ||
490 | + } | ||
491 | + | ||
492 | + if options[:highlight].is_a?(Hash) | ||
493 | + if (tag = options[:highlight][:tag]) | ||
494 | + payload[:highlight][:pre_tags] = [tag] | ||
495 | + payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")] | ||
496 | + end | ||
497 | + | ||
498 | + if (fragment_size = options[:highlight][:fragment_size]) | ||
499 | + payload[:highlight][:fragment_size] = fragment_size | ||
500 | + end | ||
501 | + if (encoder = options[:highlight][:encoder]) | ||
502 | + payload[:highlight][:encoder] = encoder | ||
503 | + end | ||
504 | + | ||
505 | + highlight_fields = options[:highlight][:fields] | ||
506 | + if highlight_fields | ||
507 | + payload[:highlight][:fields] = {} | ||
508 | + | ||
509 | + highlight_fields.each do |name, opts| | ||
510 | + payload[:highlight][:fields]["#{name}.#{@match_suffix}"] = opts || {} | ||
511 | + end | ||
512 | + end | ||
513 | + end | ||
514 | + | ||
515 | + @highlighted_fields = payload[:highlight][:fields].keys | ||
516 | + end | ||
517 | + | ||
518 | + def set_aggregations(payload) | ||
519 | + aggs = options[:aggs] | ||
520 | + payload[:aggs] = {} | ||
521 | + | ||
522 | + aggs = Hash[aggs.map { |f| [f, {}] }] if aggs.is_a?(Array) # convert to more advanced syntax | ||
523 | + | ||
524 | + aggs.each do |field, agg_options| | ||
525 | + size = agg_options[:limit] ? agg_options[:limit] : 1_000 | ||
526 | + shared_agg_options = agg_options.slice(:order) | ||
527 | + | ||
528 | + if agg_options[:ranges] | ||
529 | + payload[:aggs][field] = { | ||
530 | + range: { | ||
531 | + field: agg_options[:field] || field, | ||
532 | + ranges: agg_options[:ranges] | ||
533 | + }.merge(shared_agg_options) | ||
534 | + } | ||
535 | + elsif agg_options[:date_ranges] | ||
536 | + payload[:aggs][field] = { | ||
537 | + date_range: { | ||
538 | + field: agg_options[:field] || field, | ||
539 | + ranges: agg_options[:date_ranges] | ||
540 | + }.merge(shared_agg_options) | ||
541 | + } | ||
542 | + else | ||
543 | + payload[:aggs][field] = { | ||
544 | + terms: { | ||
545 | + field: agg_options[:field] || field, | ||
546 | + size: size | ||
547 | + }.merge(shared_agg_options) | ||
548 | + } | ||
549 | + end | ||
550 | + | ||
551 | + where = {} | ||
552 | + where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false | ||
553 | + agg_filters = where_filters(where.merge(agg_options[:where] || {})) | ||
554 | + if agg_filters.any? | ||
555 | + payload[:aggs][field] = { | ||
556 | + filter: { | ||
557 | + bool: { | ||
558 | + must: agg_filters | ||
559 | + } | ||
560 | + }, | ||
561 | + aggs: { | ||
562 | + field => payload[:aggs][field] | ||
563 | + } | ||
564 | + } | ||
565 | + end | ||
566 | + end | ||
567 | + end | ||
568 | + | ||
569 | + def set_facets(payload) | ||
570 | + facets = options[:facets] || {} | ||
571 | + facets = Hash[facets.map { |f| [f, {}] }] if facets.is_a?(Array) # convert to more advanced syntax | ||
572 | + facet_limits = {} | ||
573 | + payload[:facets] = {} | ||
574 | + facets.each do |field, facet_options| | ||
575 | + # ask for extra facets due to | ||
576 | + # https://github.com/elasticsearch/elasticsearch/issues/1305 | ||
577 | + size = facet_options[:limit] ? facet_options[:limit] + 150 : 1_000 | ||
578 | + | ||
579 | + if facet_options[:ranges] | ||
580 | + payload[:facets][field] = { | ||
581 | + range: { | ||
582 | + field.to_sym => facet_options[:ranges] | ||
583 | + } | ||
584 | + } | ||
585 | + elsif facet_options[:stats] | ||
586 | + payload[:facets][field] = { | ||
587 | + terms_stats: { | ||
588 | + key_field: field, | ||
589 | + value_script: below14? ? "doc.score" : "_score", | ||
590 | + size: size | ||
591 | + } | ||
592 | + } | ||
593 | + else | ||
594 | + payload[:facets][field] = { | ||
595 | + terms: { | ||
596 | + field: facet_options[:field] || field, | ||
597 | + size: size | ||
598 | + } | ||
599 | + } | ||
600 | + end | ||
601 | + | ||
602 | + facet_limits[field] = facet_options[:limit] if facet_options[:limit] | ||
603 | + | ||
604 | + # offset is not possible | ||
605 | + # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html | ||
606 | + | ||
607 | + facet_options.deep_merge!(where: options.fetch(:where, {}).reject { |k| k == field }) if options[:smart_facets] == true | ||
608 | + facet_filters = where_filters(facet_options[:where]) | ||
609 | + if facet_filters.any? | ||
610 | + payload[:facets][field][:facet_filter] = { | ||
611 | + and: { | ||
612 | + filters: facet_filters | ||
613 | + } | ||
614 | + } | ||
615 | + end | ||
616 | + end | ||
617 | + @facet_limits = facet_limits | ||
618 | + end | ||
619 | + | ||
620 | + def set_filters(payload, filters) | ||
621 | + if options[:facets] || options[:aggs] | ||
622 | + payload[:filter] = { | ||
623 | + and: filters | ||
624 | + } | ||
625 | + else | ||
626 | + # more efficient query if no facets | ||
627 | + payload[:query] = { | ||
628 | + filtered: { | ||
629 | + query: payload[:query], | ||
630 | + filter: { | ||
631 | + and: filters | ||
632 | + } | ||
633 | + } | ||
634 | + } | ||
635 | + end | ||
636 | + end | ||
637 | + | ||
638 | + def set_order(payload) | ||
639 | + order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc} | ||
640 | + # TODO id transformation for arrays | ||
641 | + payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? :_id : k, v] }] | ||
642 | + end | ||
643 | + | ||
616 | def where_filters(where) | 644 | def where_filters(where) |
617 | filters = [] | 645 | filters = [] |
618 | (where || {}).each do |field, value| | 646 | (where || {}).each do |field, value| |