From 3d6f99cd66f9cdc285528ff3958ea23a08907ae3 Mon Sep 17 00:00:00 2001 From: danbickford007 Date: Thu, 20 Sep 2018 20:17:54 -0400 Subject: [PATCH 1/4] Addressing issues to query within adminifi --- lib/searchkick/query.rb | 10 ++++++++-- test/sql_test.rb | 28 ++++++++++++++++++++++++++++ test/test_helper.rb | 9 ++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index 637646e03..d71d2a1f6 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -555,8 +555,14 @@ def build_query(query, filters, should, must_not, custom_filters, multiply_filte bool[:must_not] = must_not if must_not.any? # exclude bool[:should] = should if should.any? # conversions - # nested query and does not contain match all - if nested && !bool.dig(:must, :match_all) + # nested query + if nested + # If query is nested ensure dis_max queries + # is available. This allows processing of JSON + # field as nested without adding to mappings + unless bool.dig(:must, :dis_max, :queries) + bool[:must] = { dis_max: { queries: [] } } + end bool.dig(:must, :dis_max, :queries) << nested_query(nested, filters) end diff --git a/test/sql_test.rb b/test/sql_test.rb index 7b782a050..91bee893e 100644 --- a/test/sql_test.rb +++ b/test/sql_test.rb @@ -409,6 +409,34 @@ def test_where_nested end + def test_json_field + store [ + {name: 'Amazon', nested_json: {nested_field: {name: 'test1'}}}, + {name: 'Costco', nested_json: {nested_field: {name: 'test2'}}}, + {name: 'Walmart', nested_json: {nested_field: {name: 'test3'}}} + ], Store + + result = Store.search "*", { where: { + 'nested_json.nested_field.name': 'test1' + } + } + + assert_equal result.results.first.name, 'Amazon' + + result = Store.search "*", { where: { + name: 'Amazon', + nested: { + path: 'nested_field', + where: { + name: 'test1' + } + } + } + } + + assert_equal result.results.first.name, 'Amazon' + end + def test_nested_json store [ {name: 'Jim', reviews: [Review.create(name: 'Review A')]}, diff --git a/test/test_helper.rb b/test/test_helper.rb index 071002e22..9f9b2f9c5 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -383,6 +383,7 @@ class Tenant < ActiveRecord::Base ActiveRecord::Migration.create_table :stores do |t| t.string :name + t.json :nested_json end ActiveRecord::Migration.create_table :employees do |t| @@ -542,7 +543,12 @@ class Store mappings: { store: { properties: { - name: {type: "keyword"}, + nested_field: { + type: 'nested', + properties: { + name: {type: 'text'} + } + }, employees: { type: 'nested', properties: { @@ -595,6 +601,7 @@ def search_data } } } + data[:nested_field] = nested_json&.dig('nested_field') serializable_hash.except("id", "_id").merge( data ) From 09de95c8cc8de593581e8513d51bb7e87707b050 Mon Sep 17 00:00:00 2001 From: danbickford007 Date: Fri, 21 Sep 2018 06:06:05 -0400 Subject: [PATCH 2/4] Improves JSON nested query Allows for JSON field query using mapping and also using field then mapping when accessing nested data. --- lib/searchkick/query.rb | 8 ++++++++ test/sql_test.rb | 27 +++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index d71d2a1f6..625235d6f 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -863,6 +863,11 @@ def set_order(payload) def where_filters(where) filters = [] (where || {}).each do |field, value| + + # Ensure nested JSON field keys are symbols + # and not strings for processing below + value.try(:deep_symbolize_keys!) + field = :_id if field.to_s == "id" if field == :or @@ -877,6 +882,9 @@ def where_filters(where) filters << {bool: {must: value.map { |or_statement| {bool: {filter: where_filters(or_statement)}} }}} elsif field == :nested Array.wrap(value).each { |v| filters << nested_filters(v) } + elsif value.try(:keys).try(:include?, :nested) + # Handle nested field containing JSON data + Array.wrap(value).each { |v| filters << nested_filters(value[:nested]) } else # expand ranges if value.is_a?(Range) diff --git a/test/sql_test.rb b/test/sql_test.rb index 91bee893e..2f0aaf59a 100644 --- a/test/sql_test.rb +++ b/test/sql_test.rb @@ -411,11 +411,12 @@ def test_where_nested def test_json_field store [ - {name: 'Amazon', nested_json: {nested_field: {name: 'test1'}}}, - {name: 'Costco', nested_json: {nested_field: {name: 'test2'}}}, - {name: 'Walmart', nested_json: {nested_field: {name: 'test3'}}} + {name: 'Amazon', nested_json: {foo: 'bar', nested_field: {name: 'test1'}}}, + {name: 'Costco', nested_json: {foo: 'boo', nested_field: {name: 'test2'}}}, + {name: 'Walmart', nested_json: {foo: 'boo', nested_field: {name: 'test3'}}} ], Store + # Flattened dot notation result = Store.search "*", { where: { 'nested_json.nested_field.name': 'test1' } @@ -423,12 +424,30 @@ def test_json_field assert_equal result.results.first.name, 'Amazon' + # Directly access nested JSON field result = Store.search "*", { where: { name: 'Amazon', nested: { path: 'nested_field', where: { - name: 'test1' + name: 'test1' + } + } + } + } + + assert_equal result.results.first.name, 'Amazon' + + # Access JSON from field then nested mapping + result = Store.search "*", { where: { + name: 'Amazon', + nested_json: { + foo: 'bar', + nested: { + path: 'nested_field', + where: { + name: 'test1' + } } } } From 2ebcc9cf9280c456526980df3fdbcb65435673ea Mon Sep 17 00:00:00 2001 From: danbickford007 Date: Fri, 21 Sep 2018 06:32:09 -0400 Subject: [PATCH 3/4] Ensure nested picked up string or symbol Ensure we handle nested query whether nested key comes in as string or symbol. --- lib/searchkick/query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index 625235d6f..75673e98e 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -880,7 +880,7 @@ def where_filters(where) filters << {bool: {must_not: where_filters(value)}} elsif field == :_and filters << {bool: {must: value.map { |or_statement| {bool: {filter: where_filters(or_statement)}} }}} - elsif field == :nested + elsif field.to_sym == :nested Array.wrap(value).each { |v| filters << nested_filters(v) } elsif value.try(:keys).try(:include?, :nested) # Handle nested field containing JSON data From b28fa2b7afcb880467467dca4cd71b67bf877a8a Mon Sep 17 00:00:00 2001 From: danbickford007 Date: Fri, 21 Sep 2018 11:32:16 -0400 Subject: [PATCH 4/4] Bump version to 3.1.1-everfi.1 Since we want this to make it back into the mainline we are not bumping the version itself but are instead modifying it to everfi specific version --- lib/searchkick/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/searchkick/version.rb b/lib/searchkick/version.rb index 58a62d9cc..5dfa04002 100644 --- a/lib/searchkick/version.rb +++ b/lib/searchkick/version.rb @@ -1,3 +1,3 @@ module Searchkick - VERSION = "3.1.1" + VERSION = "3.1.1-everfi.1" end