elasticquery 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +12 -0
  3. data/README.md +151 -70
  4. data/Rakefile +1 -9
  5. data/elasticquery.gemspec +2 -2
  6. data/lib/elasticquery.rb +1 -0
  7. data/lib/elasticquery/base.rb +6 -48
  8. data/lib/elasticquery/builder.rb +74 -17
  9. data/lib/elasticquery/es.rb +32 -0
  10. data/lib/elasticquery/filters/base.rb +4 -0
  11. data/lib/elasticquery/filters/exists.rb +24 -0
  12. data/lib/elasticquery/filters/not.rb +7 -11
  13. data/lib/elasticquery/filters/range.rb +3 -7
  14. data/lib/elasticquery/filters/term.rb +4 -28
  15. data/lib/elasticquery/filters/terms.rb +23 -0
  16. data/lib/elasticquery/queries/base.rb +16 -0
  17. data/lib/elasticquery/queries/multi_match.rb +34 -0
  18. data/lib/elasticquery/query.rb +25 -36
  19. data/lib/elasticquery/version.rb +1 -1
  20. data/test/base_test.rb +4 -4
  21. data/test/builder_test.rb +24 -8
  22. data/test/es_test.rb +23 -0
  23. data/test/filters/exists_test.rb +30 -0
  24. data/test/filters/not_test.rb +23 -10
  25. data/test/filters/range_test.rb +10 -11
  26. data/test/filters/term_test.rb +6 -7
  27. data/test/filters/terms_test.rb +50 -0
  28. data/test/integration/chainable_call_test.rb +6 -6
  29. data/test/integration/exists_case_test.rb +56 -0
  30. data/test/integration/not_case_test.rb +11 -5
  31. data/test/integration/queries_inheritence_test.rb +12 -4
  32. data/test/integration/range_case_test.rb +4 -2
  33. data/test/integration/search_case_test.rb +20 -11
  34. data/test/integration/term_case_test.rb +4 -2
  35. data/test/integration/terms_case_test.rb +49 -0
  36. data/test/queries/multi_match_test.rb +49 -0
  37. data/test/query_test.rb +40 -40
  38. metadata +26 -27
  39. data/lib/elasticquery/filters/search.rb +0 -54
  40. data/test/filters/search_test.rb +0 -62
@@ -1,4 +1,4 @@
1
1
  module Elasticquery
2
2
  # Current gem version
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3".freeze
4
4
  end
@@ -21,7 +21,7 @@ class TestBase < MiniTest::Test
21
21
 
22
22
  def test_filters_is_empty_by_default
23
23
  query = Elasticquery::Base.new
24
- assert_empty query.filters
24
+ assert_empty query.rules
25
25
  end
26
26
 
27
27
  def test_extract_params
@@ -34,20 +34,20 @@ class TestBase < MiniTest::Test
34
34
  end
35
35
 
36
36
  def test_filters_proc
37
- assert_equal 2, @query.filters.first.call
37
+ assert_equal 2, @query.rules.first.call
38
38
  end
39
39
 
40
40
  def test_should_have_term_rule_included
41
41
  assert_respond_to @query, :term
42
42
  end
43
43
 
44
- def test_filters_as_array
44
+ def test_rules_as_array
45
45
  klass = Class.new(Elasticquery::Base)
46
46
  klass.filtered { 1 + 1 }
47
47
  klass.filtered { 2 + 2 }
48
48
 
49
49
  query = klass.new
50
- assert_equal 2, query.filters.count
50
+ assert_equal 2, query.rules.count
51
51
  end
52
52
 
53
53
  def test_should_execute_code_in_instance_context
@@ -18,24 +18,40 @@ class TestAllBaseQueries < MiniTest::Test
18
18
  assert_respond_to self, :term
19
19
  end
20
20
 
21
+ def test_have_terms
22
+ assert_respond_to self, :terms
23
+ end
24
+
21
25
  def test_have_search
22
26
  assert_respond_to self, :search
23
27
  end
24
28
 
25
- def test_defined_instances_return_sel
26
- assert_equal self, term
29
+ def test_have_multi_match
30
+ assert_respond_to self, :multi_match
27
31
  end
28
32
 
29
- def test_push_hash_term_to_query
30
- term a: 1
31
- search b: 2
32
- term c: 3
33
- assert_equal 3, query.size
33
+ def test_have_range
34
+ assert_respond_to self, :range
35
+ end
36
+
37
+ def test_have_range
38
+ assert_respond_to self, :exists
39
+ end
40
+
41
+ def test_have_range
42
+ assert_respond_to self, :with
43
+ end
44
+
45
+ def test_defined_instances_return_self
46
+ @query.expect :push_filter, true, [Elasticquery::Filters::Term]
47
+
48
+ assert_equal self, filters { term(a: 1) }
49
+ assert @query.verify
34
50
  end
35
51
 
36
52
  private
37
53
 
38
54
  def clear_query
39
- @query = []
55
+ @query = MiniTest::Mock.new
40
56
  end
41
57
  end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+ require 'elasticsearch/model'
3
+ require 'elasticquery/es'
4
+
5
+ class Searchable
6
+ include Elasticsearch::Model
7
+ end
8
+
9
+ class NotSearchable
10
+ end
11
+
12
+ class TestEs < MiniTest::Test
13
+ def setup
14
+ Searchable.extend Elasticquery::Es
15
+ @model = Searchable
16
+ end
17
+
18
+ def test_raise_error_for_not_searchable_class
19
+ assert_raises Elasticquery::EsNotSupported do
20
+ NotSearchable.extend Elasticquery::Es
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ require "test_helper"
2
+ require "elasticquery/filters/exists"
3
+
4
+ class TestExistsFilter < MiniTest::Test
5
+
6
+ def test_valid_filter_has_present_field_name
7
+ filter = Elasticquery::Filters::Exists.new "user"
8
+ assert filter.valid?
9
+ end
10
+
11
+ def test_invalid_filter_has_blank_field_name
12
+ filter = Elasticquery::Filters::Exists.new ""
13
+ refute filter.valid?
14
+ end
15
+
16
+ def test_invalid_filter_has_no_field
17
+ filter = Elasticquery::Filters::Exists.new
18
+ refute filter.valid?
19
+ end
20
+
21
+ def test_to_hash_returns_elastic_rule
22
+ filter = Elasticquery::Filters::Exists.new "user"
23
+ assert_equal filter.to_hash, {exists: {field: "user"}}
24
+ end
25
+
26
+ def test_to_not_hash_returns_missing
27
+ filter = Elasticquery::Filters::Exists.new "user"
28
+ assert_equal filter.to_not_hash, {missing: {field: "user"}}
29
+ end
30
+ end
@@ -17,37 +17,50 @@ class NotFilter < MiniTest::Test
17
17
  assert_instance_of Proc, @filter.to_hash
18
18
  end
19
19
 
20
+ def test_valid_return_proc
21
+ assert_instance_of Proc, @filter.valid?
22
+ end
23
+
24
+ def test_valid_proxy_to_previous_filter
25
+ filter_class = MiniTest::Mock.new
26
+ filter_class.expect :valid?, true
27
+ previous_filter = MiniTest::Mock.new
28
+ previous_filter.expect :dup_with, filter_class, [{a: 1}]
29
+
30
+ @filters = [previous_filter, "current-not-filter"]
31
+ assert instance_exec &@filter.valid?
32
+
33
+ assert filter_class.verify
34
+ assert previous_filter.verify
35
+ end
36
+
20
37
  def test_to_hash_change_last_term_filter_value
21
38
  filter_class = MiniTest::Mock.new
22
39
  filter_class.expect :valid?, true
23
- expected = {query: {filtered: {filter: {and: [{term: {a: 1, b: 2}}]}}}}
24
- filter_class.expect :to_hash, expected
40
+ expected = {not: {filter: {term: {a: 1, b: 2}}}}
41
+ filter_class.expect :to_not_hash, expected
25
42
  previous_filter = MiniTest::Mock.new
26
43
  previous_filter.expect :dup_with, filter_class, [{a: 1}]
27
44
 
28
- @filters = [previous_filter]
45
+ @filters = [previous_filter, "current-not-filter"]
29
46
  result = instance_exec &@filter.to_hash
30
- expected = {query: {filtered: {filter: {and: [{not: {filter: {term: {a: 1, b: 2}}}}]}}}}
31
47
  assert_equal result, expected
32
48
 
33
- assert filter_class.verify
34
49
  assert previous_filter.verify
35
50
  end
36
51
 
37
52
  def test_to_hash_change_last_range_filter_value
38
53
  filter_class = MiniTest::Mock.new
39
54
  filter_class.expect :valid?, true
40
- expected = {query: {filtered: {filter: {and: [{range: {a: {lte: 1}}}]}}}}
41
- filter_class.expect :to_hash, expected
55
+ expected = {not: {filter: {range: {a: {lte: 1}}}}}
56
+ filter_class.expect :to_not_hash, expected
42
57
  previous_filter = MiniTest::Mock.new
43
58
  previous_filter.expect :dup_with, filter_class, [{a: 1}]
44
59
 
45
- @filters = [previous_filter]
60
+ @filters = [previous_filter, "current-not-filter"]
46
61
  result = instance_exec &@filter.to_hash
47
- expected = {query: {filtered: {filter: {and: [{not: {filter: {range: {a: {lte: 1}}}}}]}}}}
48
62
  assert_equal result, expected
49
63
 
50
- assert filter_class.verify
51
64
  assert previous_filter.verify
52
65
  end
53
66
 
@@ -29,33 +29,27 @@ class RangeFilter < MiniTest::Test
29
29
 
30
30
  def test_to_hash_should_return_query
31
31
  filter = Elasticquery::Filters::Range.new :year, lte: 1, gte: 0
32
- assert_equal({query: {filtered: {filter: {and: [{range: {year: {lte: 1, gte: 0}}}]}}}}, filter.to_hash)
32
+ assert_equal({range: {year: {lte: 1, gte: 0}}}, filter.to_hash)
33
33
  end
34
34
 
35
35
  def test_to_hash_with_one_param
36
36
  filter = Elasticquery::Filters::Range.new :year, lte: 1
37
- assert_equal({query: {filtered: {filter: {and: [{range: {year: {lte: 1}}}]}}}}, filter.to_hash)
37
+ assert_equal({range: {year: {lte: 1}}}, filter.to_hash)
38
38
  end
39
39
 
40
40
  def test_to_hash_support_cache_option
41
41
  filter = Elasticquery::Filters::Range.new :year, lte: 1, _cache: true
42
- assert_equal({query: {filtered: {filter: {and: [{range: {year: {_cache: true, lte: 1}}}]}}}}, filter.to_hash)
42
+ assert_equal({range: {year: {_cache: true, lte: 1}}}, filter.to_hash)
43
43
  end
44
44
 
45
45
  def test_to_hash_support_execution_option
46
46
  filter = Elasticquery::Filters::Range.new :year, lte: 1, gte: 0, execution: "fielddata"
47
- assert_equal({query: {filtered: {filter: {and: [{range: {year: {lte: 1, gte: 0, execution: "fielddata"}}}]}}}}, filter.to_hash)
47
+ assert_equal({range: {year: {lte: 1, gte: 0, execution: "fielddata"}}}, filter.to_hash)
48
48
  end
49
49
 
50
50
  def test_to_hash_skip_unnesessary_options
51
51
  filter = Elasticquery::Filters::Range.new :year, lte: 1, _cache: true, extra: false
52
- assert_equal({query: {filtered: {filter: {and: [{range: {year: { _cache: true, lte: 1}}}]}}}}, filter.to_hash)
53
- end
54
-
55
- def test_to_hash_is_empty_if_invalid
56
- filter = Elasticquery::Filters::Range.new "year"
57
- refute filter.valid?
58
- assert_equal filter.to_hash, {}
52
+ assert_equal({range: {year: { _cache: true, lte: 1}}}, filter.to_hash)
59
53
  end
60
54
 
61
55
  def test_dup_with_return_new_range_filter
@@ -63,4 +57,9 @@ class RangeFilter < MiniTest::Test
63
57
  new_filter = filter.dup_with "month", gte: 12
64
58
  assert_kind_of Elasticquery::Filters::Range, new_filter
65
59
  end
60
+
61
+ def test_not_hash_to_returns_terms_not
62
+ filter = Elasticquery::Filters::Range.new :year, lte: 1
63
+ assert_equal({not: {filter: {range: {year: {lte: 1}}}}}, filter.to_not_hash)
64
+ end
66
65
  end
@@ -1,7 +1,7 @@
1
1
  require "test_helper"
2
2
  require "elasticquery/filters/term"
3
3
 
4
- class TestTermfilter < MiniTest::Test
4
+ class TestTermFilter < MiniTest::Test
5
5
 
6
6
  def test_valid_filter_should_have_one_key
7
7
  filter = Elasticquery::Filters::Term.new a: 1
@@ -30,18 +30,17 @@ class TestTermfilter < MiniTest::Test
30
30
 
31
31
  def test_to_hash_should_pass__cache_options
32
32
  filter = Elasticquery::Filters::Term.new a: 1, _cache: true
33
- assert_equal({query: {filtered: {filter: {and: [{term: {a: 1, _cache: true}}]}}}}, filter.to_hash)
33
+ assert_equal({term: {a: 1, _cache: true}}, filter.to_hash)
34
34
  end
35
35
 
36
36
  def test_to_hash_should_return_es_query
37
37
  filter = Elasticquery::Filters::Term.new a: 1
38
- assert_equal({query: {filtered: {filter: {and: [{term: {a: 1}}]}}}}, filter.to_hash)
38
+ assert_equal({term: {a: 1}}, filter.to_hash)
39
39
  end
40
40
 
41
- def test_to_hash_is_empty_if_invalid
42
- filter = Elasticquery::Filters::Term.new
43
- refute filter.valid?
44
- assert_equal filter.to_hash, {}
41
+ def test_not_to_hash_should_return_terms_not_query
42
+ filter = Elasticquery::Filters::Term.new a: 1
43
+ assert_equal({not: {filter: {term: {a: 1}}}}, filter.to_not_hash)
45
44
  end
46
45
 
47
46
  def test_dup_with_return_new_term_filter
@@ -0,0 +1,50 @@
1
+ require "test_helper"
2
+ require "elasticquery/filters/terms"
3
+
4
+ class TestTermsFilter < MiniTest::Test
5
+
6
+ def test_valid_filter_should_have_one_key
7
+ filter = Elasticquery::Filters::Terms.new a: 1
8
+ assert filter.valid?
9
+ end
10
+
11
+ def test_invalid_filter_should_have_no_keys
12
+ filter = Elasticquery::Filters::Terms.new
13
+ refute filter.valid?
14
+ end
15
+
16
+ def test_valid_filter_should_have_2_and_more_keys
17
+ filter = Elasticquery::Filters::Terms.new a: 1, b: 2
18
+ assert filter.valid?
19
+ end
20
+
21
+ def test_valid_filter_could_have_cache_option
22
+ filter = Elasticquery::Filters::Terms.new a: 1, _cache: false
23
+ assert filter.valid?
24
+ end
25
+
26
+ def test_invalid_with_all_blank_values
27
+ filter = Elasticquery::Filters::Terms.new a: "", b: nil
28
+ refute filter.valid?
29
+ end
30
+
31
+ def test_valid_filter_could_have_execution_option
32
+ filter = Elasticquery::Filters::Terms.new a: [1,2], b: 2, execution: "or"
33
+ assert filter.valid?
34
+ end
35
+
36
+ def test_to_hash_should_pass_all_valid_conditions
37
+ filter = Elasticquery::Filters::Terms.new a: 42, b: "42"
38
+ assert_equal({terms: {a: 42, b: "42"}}, filter.to_hash)
39
+ end
40
+
41
+ def test_to_not_hash_should_returns_terms_not_condition
42
+ filter = Elasticquery::Filters::Terms.new a: 42, b: "42"
43
+ assert_equal({not: {filter: {terms: {a: 42, b: "42"}}}}, filter.to_not_hash)
44
+ end
45
+
46
+ def test_to_hash_should_skip_blank_values
47
+ filter = Elasticquery::Filters::Terms.new a: 42, b: "", execution: "bool"
48
+ assert_equal({terms: {a: 42, execution: "bool"}}, filter.to_hash)
49
+ end
50
+ end
@@ -8,23 +8,23 @@ class TestChainableCalls < MiniTest::Test
8
8
  end
9
9
 
10
10
  def test_sign_call_return_itself
11
- assert_kind_of Elasticquery::Base, @query.term(a: 1)
11
+ assert_kind_of Elasticquery::Base, @query.filters.term(a: 1)
12
12
  end
13
13
 
14
14
  def test_apply_query
15
- query = @query.term(a: 1).term(b: 3)
15
+ query = @query.filters.term(a: 1).term(b: 3)
16
16
  assert_equal query.build, query: {filtered: {filter: {and: [{term: {a: 1}}, {term: {b: 3}}]}}}
17
17
  end
18
18
 
19
19
  def test_with_not_filter
20
- query = @query.search("hi").term.not(a: 1, _cache: true)
21
- assert_equal query.build, {query: {filtered: {query: {multi_match: {fields: "_all", operator: "and", type: "best_fields", query: "hi"}}, filter: {and: [{not: {filter: {term: {a: 1, _cache: true}}}}]}}}}
20
+ query = @query.queries.search("hi").filters.term.not(a: 1, _cache: true)
21
+ assert_equal query.build, {query: {filtered: {query: {bool: {must: [{multi_match: {fields: "_all", operator: "and", type: "best_fields", query: "hi"}}]}}, filter: {and: [{not: {filter: {term: {a: 1, _cache: true}}}}]}}}}
22
22
  end
23
23
 
24
24
  def test_apply_kinds_of_query
25
- query = @query.term(a: 1).search("hello", operator: "or").build
25
+ query = @query.filters.term(a: 1).queries.search("hello", operator: "or").build
26
26
  terms = query[:query][:filtered][:filter][:and]
27
- search = query[:query][:filtered][:query][:multi_match]
27
+ search = query[:query][:filtered][:query][:bool][:must][0][:multi_match]
28
28
  assert_equal terms, [{term: {a: 1}}]
29
29
  assert_equal search, {fields: "_all", operator: "or", type: "best_fields", query: "hello"}
30
30
  end
@@ -0,0 +1,56 @@
1
+ require "test_helper"
2
+ require "elasticquery"
3
+
4
+ class TestExistsCase < MiniTest::Test
5
+ class UserQuery < Elasticquery::Base
6
+ filtered do |params|
7
+ queries do
8
+ search params[:query]
9
+ end
10
+ filters do
11
+ exists params[:required]
12
+ with.not params[:missing]
13
+ end
14
+ end
15
+ end
16
+
17
+ class SimpleUserQuery < Elasticquery::Base
18
+ filtered do |params|
19
+ filters do
20
+ without params[:missing]
21
+ missing params[:another_missing]
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_simple_setup
27
+ params = {query: "Mark", required: "name"}
28
+ actual = UserQuery.new(params).build
29
+
30
+ expected_queries = [{multi_match: {fields: "_all", operator: "and", type: "best_fields", query: "Mark"}}]
31
+ expected_filters = [{exists: {field: "name"}}]
32
+ assert_equal expected_queries, actual[:query][:filtered][:query][:bool][:must]
33
+ assert_equal expected_filters, actual[:query][:filtered][:filter][:and]
34
+ end
35
+
36
+ def test_exists_not_use_missing
37
+ params = {query: "Mark", missing: "deleted_at"}
38
+ actual = UserQuery.new(params).build
39
+ expected_filters = [{missing: {field: "deleted_at"}}]
40
+ assert_equal expected_filters, actual[:query][:filtered][:filter][:and]
41
+ end
42
+
43
+ def test_without_support
44
+ params = {missing: "deleted_at"}
45
+ actual = SimpleUserQuery.new(params).build
46
+ expected_filters = [{missing: {field: "deleted_at"}}]
47
+ assert_equal expected_filters, actual[:query][:filtered][:filter][:and]
48
+ end
49
+
50
+ def test_missing_support
51
+ params = {another_missing: "deleted_at"}
52
+ actual = SimpleUserQuery.new(params).build
53
+ expected_filters = [{missing: {field: "deleted_at"}}]
54
+ assert_equal expected_filters, actual[:query][:filtered][:filter][:and]
55
+ end
56
+ end
@@ -4,20 +4,26 @@ require "elasticquery"
4
4
  class TestNotCase < MiniTest::Test
5
5
  class PostQuery < Elasticquery::Base
6
6
  filtered do |param|
7
- term.not id: params[:id]
7
+ filters do
8
+ term.not id: params[:id]
9
+ end
8
10
  end
9
11
  end
10
12
 
11
13
  class PostRangeQuery < Elasticquery::Base
12
14
  filtered do |param|
13
- term published: true
14
- range.not :age, lte: params[:year]
15
+ filters do
16
+ term published: true
17
+ range.not :age, lte: params[:year], _cache: false
18
+ end
15
19
  end
16
20
  end
17
21
 
18
22
  class InvalidQuery < Elasticquery::Base
19
23
  filtered do |param|
20
- term.not
24
+ filters do
25
+ term.not
26
+ end
21
27
  end
22
28
  end
23
29
 
@@ -36,7 +42,7 @@ class TestNotCase < MiniTest::Test
36
42
  def test_range_case
37
43
  params = {year: 2015}
38
44
  actual = PostRangeQuery.new(params).build
39
- expected = [{term: {published: true}}, {not: {filter: {range: {age: {lte: 2015}}}}}]
45
+ expected = [{term: {published: true}}, {not: {filter: {range: {age: {lte: 2015, _cache: false}}}}}]
40
46
  assert_equal expected, actual[:query][:filtered][:filter][:and]
41
47
  end
42
48
  end