From 587c225e951b693ac8687f1145f2d425d5e62a66 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 1 Mar 2018 01:32:29 -0800 Subject: [PATCH] Simplified queries --- lib/searchkick/query.rb | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------- 1 file changed, 59 insertions(+), 70 deletions(-) diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index 24bfd5a..297db7d 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -232,8 +232,11 @@ module Searchkick warn "The body option replaces the entire body, so the following options are ignored: #{ignored_options.join(", ")}" if ignored_options.any? payload = @json else + must_not = [] + should = [] + if options[:similar] - payload = { + query = { more_like_this: { like: term, min_doc_freq: 1, @@ -245,10 +248,10 @@ module Searchkick raise ArgumentError, "Must specify fields to search" end if fields != ["_all"] - payload[:more_like_this][:fields] = fields + query[:more_like_this][:fields] = fields end elsif all - payload = { + query = { match_all: {} } else @@ -360,9 +363,11 @@ module Searchkick queries_to_add.concat(q2) end + queries.concat(queries_to_add) + if options[:exclude] - must_not = - Array(options[:exclude]).map do |phrase| + Array(options[:exclude]).map do |phrase| + must_not << if field.start_with?("*.") { multi_match: { @@ -382,17 +387,8 @@ module Searchkick } } end - end - - queries_to_add = [{ - bool: { - should: queries_to_add, - must_not: must_not - } - }] + end end - - queries.concat(queries_to_add) end payload = { @@ -402,12 +398,8 @@ module Searchkick } if conversions_fields.present? && options[:conversions] != false - shoulds = [] conversions_fields.each do |conversions_field| - # wrap payload in a bool query - script_score = {field_value_factor: {field: "#{conversions_field}.count"}} - - shoulds << { + should << { nested: { path: conversions_field, score_mode: "sum", @@ -418,19 +410,48 @@ module Searchkick match: { "#{conversions_field}.query" => options[:conversions_term] || term } + }, + field_value_factor: { + field: "#{conversions_field}.count" } - }.merge(script_score) + } } } } end - payload = { - bool: { - must: payload, - should: shoulds - } - } end + + query = payload + end + + payload = { + size: per_page, + from: offset + } + + # type when inheritance + where = (options[:where] || {}).dup + if searchkick_options[:inheritance] && (options[:type] || (klass != searchkick_klass && searchkick_index)) + where[:type] = [options[:type] || klass].flatten.map { |v| searchkick_index.klass_document_type(v, true) } + end + + # start everything as efficient filters + # move to post_filters as aggs demand + filters = where_filters(where) + post_filters = [] + + # aggregations + set_aggregations(payload, filters, post_filters) if options[:aggs] + + # post filters + set_post_filters(payload, post_filters) if post_filters.any? + + if filters.any? || must_not.any? || should.any? + bool = {must: query} + bool[:filter] = filters if filters.any? + bool[:must_not] = must_not if must_not.any? + bool[:should] = should if should.any? + query = {bool: bool} end custom_filters = [] @@ -441,30 +462,27 @@ module Searchkick set_boost_by_distance(custom_filters) if options[:boost_by_distance] if custom_filters.any? - payload = { + query = { function_score: { functions: custom_filters, - query: payload, + query: query, score_mode: "sum" } } end if multiply_filters.any? - payload = { + query = { function_score: { functions: multiply_filters, - query: payload, + query: query, score_mode: "multiply" } } end - payload = { - query: payload, - size: per_page, - from: offset - } + payload[:query] = query + payload[:explain] = options[:explain] if options[:explain] payload[:profile] = options[:profile] if options[:profile] @@ -474,23 +492,6 @@ module Searchkick # indices_boost set_boost_by_indices(payload) - # type when inheritance - where = (options[:where] || {}).dup - if searchkick_options[:inheritance] && (options[:type] || (klass != searchkick_klass && searchkick_index)) - where[:type] = [options[:type] || klass].flatten.map { |v| searchkick_index.klass_document_type(v, true) } - end - - # start everything as efficient filters - # move to post_filters as aggs demand - filters = where_filters(where) - post_filters = [] - - # aggregations - set_aggregations(payload, filters, post_filters) if options[:aggs] - - # filters - set_filters(payload, filters, post_filters) - # suggestions set_suggestions(payload, options[:suggest]) if options[:suggest] @@ -760,24 +761,12 @@ module Searchkick end end - def set_filters(payload, filters, post_filters) - if post_filters.any? - payload[:post_filter] = { - bool: { - filter: post_filters - } - } - end - - if filters.any? - # more efficient query if no aggs - payload[:query] = { - bool: { - must: payload[:query], - filter: filters - } + def set_post_filters(payload, post_filters) + payload[:post_filter] = { + bool: { + filter: post_filters } - end + } end # TODO id transformation for arrays -- libgit2 0.21.0