daedal 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee41dfa3c33abb94b45a246a59dd12b9ed45a278
4
- data.tar.gz: 4ec21b922bb6b1e9fcd5cb94f6effad2159d8d70
3
+ metadata.gz: 01d15eb052c93f8a9dedb824873a533e876c5eee
4
+ data.tar.gz: d3408e2da2b82d8c35bf1cb07330fdb62e09c547
5
5
  SHA512:
6
- metadata.gz: 0676d06f03db74a4cf9fe0fa016f0d7197d75fc1a1c2acb21780e5b22191ff9a487f9022580a412943b62f968b8d19f9264b3a3ece0cc719475e5a70a74c47d2
7
- data.tar.gz: c7a4f7ece2fa6d1aebc00fdad3b095ff22b529a84aba9440124b6d5b607da38ce62c117cad8905a1b476fb8cfdee085e94dc27a3e9b86f09c446224f7279c0b8
6
+ metadata.gz: 1d850b9dd24946209c622306d762e8aa228994de8bdb303e19a0f572b118f42d7a6ee7df0c4ca87c17d32c512ed53f68f541e13c49bf8b28037d42072626762a
7
+ data.tar.gz: 3eb44d37d68e10dc6cec2c3a5a76b3cf9e146a8c612ed4628c36818aec056a45ab587f94577380a522c484bc60db3b9ad0df4c3b97a9e2bc545f92ef7e15b701
data/README.md CHANGED
@@ -1,4 +1,171 @@
1
1
  Daedal
2
- =====================
2
+ ======
3
3
 
4
- Ruby classes for easier ElasticSearch query building
4
+ This repository contains a set of Ruby classes designed to make ElasticSearch
5
+ query creation simpler and easier to debug. The goal is to reproduce all
6
+ components of the ElasticSearch [Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html)
7
+ to aid in the construction of complex queries. Type checking and attribute
8
+ coercion are handled using [Virtus](https://github.com/solnic/virtus) to make
9
+ it harder to construct invalid ElasticSearch queries before sending them to the server.
10
+
11
+ The ElasticSearch Query DSL is huge! There are also a ton of different options within each
12
+ component. My goal is to include as much of that functionality and flexibility as possible, but
13
+ also maintain as high of test coverage as possible. That means it'll take some time for this project
14
+ to reach full coverage of the Query DSL, so please feel free to contribute or be patient :)
15
+
16
+ Installation
17
+ ------------
18
+
19
+ ``` terminal
20
+ $ gem install daedal
21
+ ```
22
+
23
+ or in your `Gemfile`
24
+
25
+ ``` ruby
26
+ gem 'daedal'
27
+ ```
28
+
29
+ Usage
30
+ --------
31
+
32
+ ### ElasticSearch Query DSL
33
+
34
+ Other Ruby packages for ElasticSearch allow you to create queries either as
35
+ hashes or by constructing raw JSON:
36
+
37
+ ``` ruby
38
+ match_query = {'match' => {'foo' => {'query' => 'bar'}}}
39
+ ```
40
+
41
+ For more complicated queries, dealing with the resulting large nested hash can be
42
+ frustrating. Inspired by ElasticSearch's built in
43
+ [Java API](http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/current/),
44
+ Daedal contains Ruby classes designed to make query construction more Ruby-like.
45
+
46
+ ### Queries
47
+
48
+ Queries are contained within the `Queries` module. You can construct query components like:
49
+
50
+ ``` ruby
51
+ require 'daedal'
52
+
53
+ # creates the basic match query
54
+ match_query = Daedal::Queries::MatchQuery.new(field: 'foo', query: 'bar')
55
+ ```
56
+ Each query object has `#to_json` defined for easy conversion for use with any of the Ruby
57
+ ElasticSearch clients out there:
58
+ ``` ruby
59
+ match_query.to_json # => "{\"match\":{\"foo\":{\"query\":\"bar\"}}}"
60
+ ```
61
+
62
+ To date (12/8/2013), I have implemented the following queries:
63
+ * [bool query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)
64
+ * [constant score query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html)
65
+ * [dis max query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html)
66
+ * [filtered query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html)
67
+ * [match all query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html)
68
+ * [match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-query.html)
69
+ * [multi match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html)
70
+
71
+ ### Filters
72
+
73
+ Filters are contained within the `Filters` module. You can construct filter components
74
+ in the same way as queries:
75
+
76
+ ``` ruby
77
+ require 'daedal'
78
+
79
+ term_filter = Daedal::Filters::TermFilter.new(field: 'foo', term: 'bar')
80
+
81
+ term_filter.to_json # => "{\"term\":{\"foo\":\"bar\"}}"
82
+ ```
83
+
84
+ To date (12/8/2013), I have implemented the following filters:
85
+ * [term filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-filter.html)
86
+
87
+ ### Type checking and attribute coercion
88
+
89
+ When creating ElasticSearch queries via nested hashes, it is all too easy to
90
+ assign an invalid value to a specific field, which would then result in
91
+ an error response when sending the query to the server. For instance, the query:
92
+
93
+ ``` ruby
94
+ constant_score_query = {'constant_score' => {'boost' => 'foo', 'query': {'match_all': {}}}}
95
+ ```
96
+
97
+ would yield a server error, since the `boost` parameter must be a number.
98
+
99
+ Daedal uses [Virtus](https://github.com/solnic/virtus) to perform data-type coercions.
100
+ That way, invalid query parameters are surfaced at runtime, making debugging easier.
101
+ The previous `constant_score_query` example in Daedal would raise an error:
102
+
103
+ ``` ruby
104
+ match_all_query = Daedal::Queries::MatchAllQuery.new()
105
+ constant_score_query = Daedal::Queries::ConstantScoreQuery.new(boost: 'foo', query: match_all_query)
106
+
107
+ # Virtus::CoercionError: Failed to coerce "foo" into Float
108
+ ```
109
+
110
+ ### Creating your own queries
111
+
112
+ Currently, I've only made it through a fraction of the entire Query DSL, but will be working to
113
+ achieve complete coverage as quickly as possible. If you need to use a query that
114
+ I haven't gotten to yet, or if you want to create your own more specialized queries within
115
+ your own project, defining the query classes is relatively straightforward - just make
116
+ your new class a sublass of the `Daedal::Queries::BaseQuery` or `Daedal::Filters::BaseFilter`
117
+ classes, and define the `to_hash` method. All methods made available by including `Virtus.model` in your
118
+ class will be available to you, as well.
119
+
120
+ Example:
121
+ ``` ruby
122
+ class MyQuery < Daedal::Queries::BaseQuery
123
+
124
+ # define the attributes that you need in your query
125
+ attribute :foo, String
126
+ attribute :bar, String
127
+
128
+ # define the to_hash method to convert for use in ElasticSearch
129
+ def to_hash
130
+ ...
131
+ end
132
+ end
133
+ ```
134
+
135
+ Contributing
136
+ -------------
137
+
138
+ The ElasticSearch Query DSL is pretty large and includes a ton of nuance. I'm starting with the
139
+ most basic parts of the DSL (and the parts I use for work), so if you want to help out with the project
140
+ to meet your needs please feel free to contribute! I just ask that you:
141
+
142
+ * Fork the project.
143
+ * Make your changes or additions.
144
+ * Add tests! My goal is complete test coverage, so please take the effort to make them pretty comprehensive.
145
+ * Send me a pull request.
146
+
147
+ Feedback or suggestions are also always welcome.
148
+
149
+ License
150
+ -------
151
+
152
+ The MIT License (MIT)
153
+
154
+ Copyright (c) 2013 Christopher Schuch
155
+
156
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
157
+ this software and associated documentation files (the "Software"), to deal in
158
+ the Software without restriction, including without limitation the rights to
159
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
160
+ the Software, and to permit persons to whom the Software is furnished to do so,
161
+ subject to the following conditions:
162
+
163
+ The above copyright notice and this permission notice shall be included in all
164
+ copies or substantial portions of the Software.
165
+
166
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
168
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
169
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
170
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
171
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,6 +1,8 @@
1
+ require File.expand_path('../lib/daedal/version', __FILE__)
2
+
1
3
  Gem::Specification.new do |s|
2
4
  s.name = 'daedal'
3
- s.version = '0.0.2'
5
+ s.version = Daedal::VERSION
4
6
  s.date = '2013-12-06'
5
7
  s.summary = "ElasticSearch Query DSL Builders"
6
8
  s.description = "Classes for easier ElasticSearch query creation"
@@ -11,4 +13,6 @@ Gem::Specification.new do |s|
11
13
  s.license = 'MIT'
12
14
  s.homepage =
13
15
  'https://github.com/cschuch/daedal'
16
+
17
+ s.add_dependency('virtus', '~> 1.0.0')
14
18
  end
@@ -1,4 +1,5 @@
1
1
  require 'json'
2
+
2
3
  require 'daedal/queries'
3
4
  require 'daedal/filters'
4
5
  require 'daedal/attributes'
@@ -1,94 +1,10 @@
1
1
  require 'virtus'
2
- require 'daedal/queries/base_query'
3
- require 'daedal/filters/base_filter'
2
+ require 'daedal/attributes/operator'
3
+ require 'daedal/attributes/match_type'
4
+ require 'daedal/attributes/query_array'
5
+ require 'daedal/attributes/score_mode'
4
6
 
5
7
  module Daedal
6
8
  module Attributes
7
-
8
- """Custom coercer for a query, allowing nil"""
9
- class QueryOrNil < Virtus::Attribute
10
- def coerce(value)
11
- unless value.is_a? Daedal::Queries::BaseQuery or value.nil?
12
- raise "Invalid query"
13
- end
14
- value
15
- end
16
- end
17
-
18
- """Custom coercer for a filter, allowing nil"""
19
- class FilterOrNil < Virtus::Attribute
20
- def coerce(value)
21
- unless value.is_a? Daedal::Filters::BaseFilter or value.nil?
22
- raise "Invalid filter"
23
- end
24
- value
25
- end
26
- end
27
-
28
- """Custom coercer for a query"""
29
- class Query < Virtus::Attribute
30
- def coerce(value)
31
- unless value.is_a? Daedal::Queries::BaseQuery
32
- raise "Must give a query"
33
- end
34
- value
35
- end
36
- end
37
-
38
- """Custom coercer for a filter"""
39
- class Filter < Virtus::Attribute
40
- def coerce(value)
41
- unless value.is_a? Daedal::Filters::BaseFilter
42
- raise "Must give a filter"
43
- end
44
- value
45
- end
46
- end
47
-
48
- """Custom coercer for an array of queries"""
49
- class QueryArray < Virtus::Attribute
50
- def coerce(value)
51
- unless value.is_a? Array
52
- value = [value]
53
- end
54
-
55
- value.each do |q|
56
- unless q.is_a? Daedal::Queries::BaseQuery
57
- raise "Must give an array of queries"
58
- end
59
- end
60
-
61
- value
62
- end
63
- end
64
-
65
- """Custom coercer for the operator attribute"""
66
- class Operator < Virtus::Attribute
67
- ALLOWED_MATCH_OPERATORS = [:or, :and]
68
- def coerce(value)
69
- unless value.nil?
70
- value = value.to_sym
71
- unless ALLOWED_MATCH_OPERATORS.include? value
72
- raise "#{value} is not a valid operator. Allowed values are #{ALLOWED_MATCH_OPERATORS}."
73
- end
74
- end
75
- value
76
- end
77
- end
78
-
79
- """Custom coercer for the type attribute"""
80
- class MatchType < Virtus::Attribute
81
- ALLOWED_MATCH_TYPES = [:phrase, :phrase_prefix]
82
- def coerce(value)
83
- unless value.nil?
84
- value = value.to_sym
85
- unless ALLOWED_MATCH_TYPES.include? value
86
- raise "#{value} is not a valid type. Allowed values are #{ALLOWED_MATCH_TYPES}."
87
- end
88
- end
89
- value
90
- end
91
- end
92
-
93
9
  end
94
10
  end
@@ -0,0 +1,17 @@
1
+ module Daedal
2
+ module Attributes
3
+ """Custom coercer for the type attribute"""
4
+ class MatchType < Virtus::Attribute
5
+ ALLOWED_MATCH_TYPES = [:phrase, :phrase_prefix]
6
+ def coerce(value)
7
+ unless value.nil?
8
+ value = value.to_sym
9
+ unless ALLOWED_MATCH_TYPES.include? value
10
+ raise Virtus::CoercionError.new(value, 'Daedal::Attributes::MatchType')
11
+ end
12
+ end
13
+ value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Daedal
2
+ module Attributes
3
+ """Custom coercer for the operator attribute"""
4
+ class Operator < Virtus::Attribute
5
+ ALLOWED_MATCH_OPERATORS = [:or, :and]
6
+ def coerce(value)
7
+ unless value.nil?
8
+ value = value.to_sym
9
+ unless ALLOWED_MATCH_OPERATORS.include? value
10
+ raise Virtus::CoercionError.new(value, 'Daedal::Attributes::Operator')
11
+ end
12
+ end
13
+ value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Daedal
2
+ module Attributes
3
+ """Custom attribute for an array of queries"""
4
+ class QueryArray < Array
5
+ # override the << method so that you throw
6
+ # an error if you don't try to append a query
7
+ def <<(q)
8
+ if q.is_a? Daedal::Queries::BaseQuery
9
+ super q
10
+ else
11
+ raise Virtus::CoercionError.new(q, 'Daedal::Queries::BaseQuery')
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Daedal
2
+ module Attributes
3
+ """Custom coercer for the type attribute"""
4
+ class ScoreMode < Virtus::Attribute
5
+ ALLOWED_SCORE_MODES = [:avg, :total, :max, :none]
6
+ def coerce(value)
7
+ unless value.nil?
8
+ value = value.to_sym
9
+ unless ALLOWED_SCORE_MODES.include? value
10
+ raise Virtus::CoercionError.new(value, 'Daedal::Attributes::MatchType')
11
+ end
12
+ end
13
+ value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,6 @@
1
1
  require 'daedal/filters/base_filter'
2
2
  require 'daedal/filters/term_filter'
3
+ require 'daedal/filters/terms_filter'
3
4
 
4
5
  module Daedal
5
6
  module Filters
@@ -3,7 +3,7 @@ require 'daedal/attributes'
3
3
 
4
4
  module Daedal
5
5
  module Filters
6
- """Class for the basic match query"""
6
+ """Class for the basic term filter"""
7
7
  class TermFilter < BaseFilter
8
8
 
9
9
  # required attributes
@@ -0,0 +1,18 @@
1
+ require 'daedal/filters/base_filter'
2
+ require 'daedal/attributes'
3
+
4
+ module Daedal
5
+ module Filters
6
+ """Class for the basic term filter"""
7
+ class TermsFilter < BaseFilter
8
+
9
+ # required attributes
10
+ attribute :field, Symbol
11
+ attribute :terms, Array[Symbol]
12
+
13
+ def to_hash
14
+ {terms: {field => terms}}
15
+ end
16
+ end
17
+ end
18
+ end
@@ -6,6 +6,7 @@ require 'daedal/queries/filtered_query'
6
6
  require 'daedal/queries/match_all_query'
7
7
  require 'daedal/queries/match_query'
8
8
  require 'daedal/queries/multi_match_query'
9
+ require 'daedal/queries/nested_query'
9
10
 
10
11
  module Daedal
11
12
  module Queries
@@ -2,9 +2,18 @@ require 'virtus'
2
2
 
3
3
  module Daedal
4
4
  module Queries
5
+
6
+ """Base class for queries. All other queries
7
+ should inherit from this class directly in order to
8
+ allow for data-type coercion for compound queries
9
+ like the bool or dis max query"""
5
10
  class BaseQuery
11
+ # Virtus coercion is set to strict so that errors
12
+ # are returned when supplied fields cannot be properly
13
+ # coerced.
6
14
  include Virtus.model strict: true
7
15
 
16
+ # requires the subclasses to define #to_hash
8
17
  def to_json
9
18
  to_hash.to_json
10
19
  end
@@ -3,42 +3,25 @@ require 'daedal/attributes'
3
3
 
4
4
  module Daedal
5
5
  module Queries
6
- """Class for the basic match query"""
6
+ """Class for the bool query"""
7
7
  class BoolQuery < BaseQuery
8
8
 
9
9
  # required attributes
10
- attribute :should, Attributes::QueryArray, default: Array.new
11
- attribute :must, Attributes::QueryArray, default: Array.new
12
- attribute :must_not, Attributes::QueryArray, default: Array.new
10
+
11
+ # should, must, and must_not must be an array of queries
12
+ # these queries must inherit from the BaseQuery class
13
+ attribute :should, Attributes::QueryArray[Daedal::Queries::BaseQuery], default: Array.new
14
+ attribute :must, Attributes::QueryArray[Daedal::Queries::BaseQuery], default: Array.new
15
+ attribute :must_not, Attributes::QueryArray[Daedal::Queries::BaseQuery], default: Array.new
13
16
 
14
17
  # non required attributes
15
18
  attribute :minimum_should_match, Integer, required: false
16
19
  attribute :boost, Integer, required: false
17
-
18
- def verify_query(q)
19
- unless q.is_a? Daedal::Queries::BaseQuery
20
- raise "Must give a valid query"
21
- end
22
- end
23
-
24
- def add_should_query(q)
25
- verify_query(q)
26
- should << q
27
- end
28
-
29
- def add_must_query(q)
30
- verify_query(q)
31
- must << q
32
- end
33
-
34
- def add_must_not_query(q)
35
- verify_query(q)
36
- must_not << q
37
- end
20
+ attribute :name, Symbol, required: false
38
21
 
39
22
  def to_hash
40
23
  result = {bool: {should: should.map {|q| q.to_hash}, must: must.map {|q| q.to_hash}, must_not: must_not.map {|q| q.to_hash}}}
41
- options = {minimum_should_match: minimum_should_match, boost: boost}
24
+ options = {minimum_should_match: minimum_should_match, boost: boost, _name: name}
42
25
  result[:bool].merge!(options.select { |k,v| !v.nil? })
43
26
 
44
27
  result
@@ -1,18 +1,20 @@
1
1
  require 'daedal/queries/base_query'
2
+ require 'daedal/filters/base_filter'
2
3
  require 'daedal/attributes'
3
4
 
4
5
  module Daedal
5
6
  module Queries
6
- """Class for the basic match query"""
7
+ """Class for the constant score query"""
7
8
  class ConstantScoreQuery < BaseQuery
8
9
 
9
10
  # required attributes
10
11
  attribute :boost, Float
11
12
 
12
13
  # non required attributes, but one must be required of the two
13
- attribute :query, Attributes::QueryOrNil
14
- attribute :filter, Attributes::FilterOrNil
14
+ attribute :query, Daedal::Queries::BaseQuery, required: false
15
+ attribute :filter, Daedal::Filters::BaseFilter, required: false
15
16
 
17
+ # you must require *one of* query or filter in order for this to be valid
16
18
  def initialize(options={})
17
19
  super options
18
20
  if query.nil? && filter.nil?
@@ -4,27 +4,16 @@ require 'daedal/attributes'
4
4
  module Daedal
5
5
  module Queries
6
6
 
7
- """Class for the basic match query"""
7
+ """Class for the dis max query"""
8
8
  class DisMaxQuery < BaseQuery
9
9
 
10
10
  # required attributes
11
- attribute :queries, Attributes::QueryArray, default: Array.new
11
+ attribute :queries, Attributes::QueryArray[Daedal::Queries::BaseQuery], default: Array.new
12
12
 
13
13
  # non required attributes
14
14
  attribute :tie_breaker, Float, required: false
15
15
  attribute :boost, Integer, required: false
16
16
 
17
- def verify_query(q)
18
- unless q.is_a? Daedal::Queries::BaseQuery
19
- raise "Must give a valid query"
20
- end
21
- end
22
-
23
- def add_query(q)
24
- verify_query(q)
25
- queries << q
26
- end
27
-
28
17
  def to_hash
29
18
  result = {dis_max: {queries: queries.map {|q| q.to_hash }}}
30
19
  options = {tie_breaker: tie_breaker, boost: boost}
@@ -5,12 +5,12 @@ require 'daedal/attributes'
5
5
 
6
6
  module Daedal
7
7
  module Queries
8
- """Class for the basic match query"""
8
+ """Class for the filtered query"""
9
9
  class FilteredQuery < BaseQuery
10
10
 
11
11
  # required attributes
12
- attribute :query, Attributes::Query, default: Daedal::Queries::MatchAllQuery.new
13
- attribute :filter, Attributes::Filter, default: Daedal::Filters::BaseFilter.new
12
+ attribute :query, Daedal::Queries::BaseQuery, default: Daedal::Queries::MatchAllQuery.new
13
+ attribute :filter, Daedal::Filters::BaseFilter, default: Daedal::Filters::BaseFilter.new
14
14
 
15
15
  def to_hash
16
16
  {filtered: {query: query.to_hash, filter: filter.to_hash}}
@@ -2,7 +2,7 @@ require 'daedal/queries/base_query'
2
2
 
3
3
  module Daedal
4
4
  module Queries
5
- """Class for the basic match query"""
5
+ """Class for the match all query"""
6
6
  class MatchAllQuery < BaseQuery
7
7
  def to_hash
8
8
  {match_all: {}}
@@ -4,7 +4,7 @@ require 'daedal/attributes'
4
4
  module Daedal
5
5
  module Queries
6
6
 
7
- """Class for the basic match query"""
7
+ """Class for the match query"""
8
8
  class MatchQuery < BaseQuery
9
9
 
10
10
  # required attributes
@@ -4,7 +4,7 @@ require 'daedal/attributes'
4
4
  module Daedal
5
5
  module Queries
6
6
 
7
- """Class for the multi_match query"""
7
+ """Class for the multi match query"""
8
8
  class MultiMatchQuery < BaseQuery
9
9
 
10
10
  # required attributes
@@ -22,6 +22,7 @@ module Daedal
22
22
  attribute :boost, Integer, required: false
23
23
  attribute :fuzziness, Float, required: false
24
24
 
25
+ # Fields cannot be an empty array... should eventually refactor this kind of thing out of initialize
25
26
  def initialize(options={})
26
27
  super options
27
28
 
@@ -0,0 +1,26 @@
1
+ require 'daedal/queries/base_query'
2
+ require 'daedal/attributes'
3
+
4
+ module Daedal
5
+ module Queries
6
+ """Class for the bool query"""
7
+ class NestedQuery < BaseQuery
8
+
9
+ # required attributes
10
+ attribute :path, Symbol
11
+ attribute :query, Daedal::Queries::BaseQuery
12
+
13
+ # non required attributes
14
+ attribute :score_mode, Attributes::ScoreMode, required: false
15
+
16
+ def to_hash
17
+ result = {nested: {path: path, query: query.to_hash}}
18
+ unless score_mode.nil?
19
+ result[:nested][:score_mode] = score_mode
20
+ end
21
+
22
+ result
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'daedal/filters'
3
+
4
+ describe Daedal::Filters::TermsFilter do
5
+
6
+ subject do
7
+ Daedal::Filters::TermsFilter
8
+ end
9
+
10
+ let(:field) do
11
+ :foo
12
+ end
13
+
14
+ let(:terms) do
15
+ [:foo, :bar]
16
+ end
17
+
18
+ let(:hash_filter) do
19
+ {terms: {field => terms}}
20
+ end
21
+
22
+ context 'without a field or a list of terms specified' do
23
+ it 'will raise an error' do
24
+ expect {subject.new}.to raise_error
25
+ end
26
+ end
27
+
28
+ context 'without a field specified' do
29
+ it 'will raise an error' do
30
+ expect {subject.new(terms: terms)}.to raise_error
31
+ end
32
+ end
33
+
34
+ context 'with a field and a list of terms specified' do
35
+ let(:filter) do
36
+ subject.new(field: field, terms: terms.map {|t| t.to_s})
37
+ end
38
+ it 'will populate the field and term attributes appropriately' do
39
+ expect(filter.field).to eq field
40
+ expect(filter.terms).to eq terms
41
+ end
42
+ it 'will have the correct hash representation' do
43
+ expect(filter.to_hash).to eq hash_filter
44
+ end
45
+ it 'will have the correct json representation' do
46
+ expect(filter.to_json).to eq hash_filter.to_json
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'daedal/queries'
3
+ require 'debugger'
3
4
 
4
5
  describe Daedal::Queries::BoolQuery do
5
6
 
@@ -136,9 +137,9 @@ describe Daedal::Queries::BoolQuery do
136
137
  match_query.new(field: :a, query: :b)
137
138
  end
138
139
 
139
- context 'with the #add_should_query method' do
140
+ context 'with the should.<< method' do
140
141
  before do
141
- query.add_should_query mq
142
+ query.should << mq
142
143
  end
143
144
  it 'will add a should query' do
144
145
  expect(query.should).to eq [mq]
@@ -146,7 +147,7 @@ describe Daedal::Queries::BoolQuery do
146
147
 
147
148
  context 'twice' do
148
149
  before do
149
- query.add_should_query mq
150
+ query.should << mq
150
151
  end
151
152
  it 'will append the second query' do
152
153
  expect(query.should).to eq [mq, mq]
@@ -155,14 +156,14 @@ describe Daedal::Queries::BoolQuery do
155
156
 
156
157
  context 'with a non-valid query' do
157
158
  it 'will raise an error' do
158
- expect{query.add_should_query :foo}.to raise_error
159
+ expect{query.should << :foo}.to raise_error
159
160
  end
160
161
  end
161
162
  end
162
163
 
163
- context 'with the #add_must_query method' do
164
+ context 'with the must.<< method' do
164
165
  before do
165
- query.add_must_query mq
166
+ query.must << mq
166
167
  end
167
168
 
168
169
  it 'will add a should query' do
@@ -171,7 +172,7 @@ describe Daedal::Queries::BoolQuery do
171
172
 
172
173
  context 'twice' do
173
174
  before do
174
- query.add_must_query mq
175
+ query.must << mq
175
176
  end
176
177
  it 'will append the second query' do
177
178
  expect(query.must).to eq [mq, mq]
@@ -180,15 +181,15 @@ describe Daedal::Queries::BoolQuery do
180
181
 
181
182
  context 'with a non-valid query' do
182
183
  it 'will raise an error' do
183
- expect {query.add_must_query :foo}.to raise_error
184
+ expect {query.must << :foo}.to raise_error
184
185
  end
185
186
  end
186
187
 
187
188
  end
188
189
 
189
- context 'with the #add_must_not_query method' do
190
+ context 'with the must_not.<< method' do
190
191
  before do
191
- query.add_must_not_query mq
192
+ query.must_not << mq
192
193
  end
193
194
 
194
195
  it 'will add a must_not query' do
@@ -197,7 +198,7 @@ describe Daedal::Queries::BoolQuery do
197
198
 
198
199
  context 'twice' do
199
200
  before do
200
- query.add_must_not_query mq
201
+ query.must_not << mq
201
202
  end
202
203
  it 'will append the second query' do
203
204
  expect(query.must_not).to eq [mq, mq]
@@ -206,7 +207,7 @@ describe Daedal::Queries::BoolQuery do
206
207
 
207
208
  context 'with a non-valid query' do
208
209
  it 'will raise an error' do
209
- expect {query.add_must_not_query :foo}.to raise_error
210
+ expect {query.must_not << :foo}.to raise_error
210
211
  end
211
212
  end
212
213
  end
@@ -36,6 +36,18 @@ describe Daedal::Queries::ConstantScoreQuery do
36
36
  end
37
37
  end
38
38
 
39
+ context 'with a boost but an invalid query specified' do
40
+ it 'will raise an error' do
41
+ expect {subject.new(boost: 5, query: :foo)}.to raise_error
42
+ end
43
+ end
44
+
45
+ context 'with a boost but an invalid filter specified' do
46
+ it 'will raise an error' do
47
+ expect {subject.new(boost: 5, filter: :foo)}.to raise_error
48
+ end
49
+ end
50
+
39
51
  context 'with a query and a boost specified' do
40
52
  let(:query) do
41
53
  subject.new(query: match_query, boost: 5)
@@ -124,9 +124,9 @@ describe Daedal::Queries::DisMaxQuery do
124
124
  match_query.new(field: :a, query: :b)
125
125
  end
126
126
 
127
- context 'with the #add_query method' do
127
+ context 'with the queries.<< method' do
128
128
  before do
129
- query.add_query mq
129
+ query.queries << mq
130
130
  end
131
131
  it 'will add a query' do
132
132
  expect(query.queries).to eq [mq]
@@ -134,7 +134,7 @@ describe Daedal::Queries::DisMaxQuery do
134
134
 
135
135
  context 'twice' do
136
136
  before do
137
- query.add_query mq
137
+ query.queries << mq
138
138
  end
139
139
  it 'will append the second query' do
140
140
  expect(query.queries).to eq [mq, mq]
@@ -143,7 +143,7 @@ describe Daedal::Queries::DisMaxQuery do
143
143
 
144
144
  context 'with a non-valid query' do
145
145
  it 'will raise an error' do
146
- expect{query.add_query :foo}.to raise_error
146
+ expect{query.queries << :foo}.to raise_error
147
147
  end
148
148
  end
149
149
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'daedal/queries'
3
+ require 'daedal/filters'
3
4
 
4
5
  describe Daedal::Queries::FilteredQuery do
5
6
 
@@ -40,6 +41,18 @@ describe Daedal::Queries::FilteredQuery do
40
41
  end
41
42
  end
42
43
 
44
+ context 'with an invalid query specified' do
45
+ it 'will raise an error' do
46
+ expect{subject.new(query: :foo)}.to raise_error
47
+ end
48
+ end
49
+
50
+ context 'with an invalid filter specified' do
51
+ it 'will raise an error' do
52
+ expect{subject.new(filter: :foo)}.to raise_error
53
+ end
54
+ end
55
+
43
56
  context 'with a query and a filter specified' do
44
57
  let(:query) do
45
58
  subject.new(query: match_query, filter: term_filter)
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+ require 'daedal/queries'
3
+ require 'daedal/filters'
4
+
5
+ describe Daedal::Queries::NestedQuery do
6
+
7
+ subject do
8
+ Daedal::Queries::NestedQuery
9
+ end
10
+
11
+ let(:match_all_query) do
12
+ Daedal::Queries::MatchAllQuery.new
13
+ end
14
+
15
+ context 'with no path specified' do
16
+ it 'will raise an error' do
17
+ expect{subject.new(query: match_all_query)}.to raise_error
18
+ end
19
+ end
20
+
21
+ context 'with no query specified' do
22
+ it 'will raise an error' do
23
+ expect{subject.new(path: 'foo')}.to raise_error
24
+ end
25
+ end
26
+
27
+ context 'with an invalid query specified' do
28
+ it 'will raise an error' do
29
+ expect{subject.new(query: :foo)}.to raise_error
30
+ end
31
+ end
32
+
33
+ context 'with a query and a path specified' do
34
+ let(:query) do
35
+ subject.new query: match_all_query, path: :foo
36
+ end
37
+ let(:hash_query) do
38
+ {nested: {path: :foo, query: match_all_query.to_hash}}
39
+ end
40
+
41
+ it 'will create a nested query with the appropriate fields' do
42
+ expect(query.query).to eq match_all_query
43
+ expect(query.path).to eq :foo
44
+ end
45
+
46
+ it 'will have the correct hash representation' do
47
+ expect(query.to_hash).to eq hash_query
48
+ end
49
+
50
+ it 'will have the correct json representation' do
51
+ expect(query.to_json).to eq hash_query.to_json
52
+ end
53
+ end
54
+
55
+ context 'with score_mode specified' do
56
+ let(:query) do
57
+ subject.new query: match_all_query, path: :foo, score_mode: :avg
58
+ end
59
+ let(:hash_query) do
60
+ {nested: {path: :foo, query: match_all_query.to_hash, score_mode: :avg}}
61
+ end
62
+
63
+ it 'will create a nested query with the appropriate fields' do
64
+ expect(query.query).to eq match_all_query
65
+ expect(query.path).to eq :foo
66
+ expect(query.score_mode).to eq :avg
67
+ end
68
+
69
+ it 'will have the correct hash representation' do
70
+ expect(query.to_hash).to eq hash_query
71
+ end
72
+ it 'will have the correct json representation' do
73
+ expect(query.to_json).to eq hash_query.to_json
74
+ end
75
+ end
76
+
77
+ context 'with an invalid score_mode specified' do
78
+ it 'will raise an error' do
79
+ expect{subject.new(query: match_all_query, path: :foo, score_mode: 'foo')}.to raise_error
80
+ end
81
+ end
82
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daedal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Schuch
@@ -9,7 +9,21 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2013-12-06 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: virtus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
13
27
  description: Classes for easier ElasticSearch query creation
14
28
  email: cas13091@gmail.com
15
29
  executables: []
@@ -26,9 +40,14 @@ files:
26
40
  - daedal.gemspec
27
41
  - lib/daedal.rb
28
42
  - lib/daedal/attributes.rb
43
+ - lib/daedal/attributes/match_type.rb
44
+ - lib/daedal/attributes/operator.rb
45
+ - lib/daedal/attributes/query_array.rb
46
+ - lib/daedal/attributes/score_mode.rb
29
47
  - lib/daedal/filters.rb
30
48
  - lib/daedal/filters/base_filter.rb
31
49
  - lib/daedal/filters/term_filter.rb
50
+ - lib/daedal/filters/terms_filter.rb
32
51
  - lib/daedal/queries.rb
33
52
  - lib/daedal/queries/base_query.rb
34
53
  - lib/daedal/queries/bool_query.rb
@@ -38,8 +57,10 @@ files:
38
57
  - lib/daedal/queries/match_all_query.rb
39
58
  - lib/daedal/queries/match_query.rb
40
59
  - lib/daedal/queries/multi_match_query.rb
60
+ - lib/daedal/queries/nested_query.rb
41
61
  - spec/spec_helper.rb
42
62
  - spec/unit/daedal/filters/term_filter_spec.rb
63
+ - spec/unit/daedal/filters/terms_filter_spec.rb
43
64
  - spec/unit/daedal/queries/bool_query_spec.rb
44
65
  - spec/unit/daedal/queries/constant_score_query_spec.rb
45
66
  - spec/unit/daedal/queries/dis_max_query_spec.rb
@@ -47,6 +68,7 @@ files:
47
68
  - spec/unit/daedal/queries/match_all_query_spec.rb
48
69
  - spec/unit/daedal/queries/match_query_spec.rb
49
70
  - spec/unit/daedal/queries/multi_match_query_spec.rb
71
+ - spec/unit/daedal/queries/nested_query_spec.rb
50
72
  homepage: https://github.com/cschuch/daedal
51
73
  licenses:
52
74
  - MIT