daedal 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -1
  3. data/.travis.yml +7 -0
  4. data/Gemfile +9 -7
  5. data/Gemfile.lock +47 -32
  6. data/README.md +115 -56
  7. data/daedal.gemspec +0 -1
  8. data/lib/daedal.rb +41 -5
  9. data/lib/daedal/attributes/boost.rb +7 -0
  10. data/lib/daedal/attributes/facet.rb +13 -0
  11. data/lib/daedal/attributes/field.rb +7 -0
  12. data/lib/daedal/attributes/filter.rb +2 -2
  13. data/lib/daedal/attributes/filter_array.rb +4 -4
  14. data/lib/daedal/attributes/query.rb +2 -2
  15. data/lib/daedal/attributes/query_array.rb +2 -2
  16. data/lib/daedal/attributes/query_value.rb +19 -0
  17. data/lib/daedal/facets/facet.rb +15 -0
  18. data/lib/daedal/filters/and_filter.rb +2 -5
  19. data/lib/daedal/filters/bool_filter.rb +15 -0
  20. data/lib/daedal/filters/{base_filter.rb → filter.rb} +1 -3
  21. data/lib/daedal/filters/geo_distance_filter.rb +6 -9
  22. data/lib/daedal/filters/or_filter.rb +18 -0
  23. data/lib/daedal/filters/range_filter.rb +8 -8
  24. data/lib/daedal/filters/term_filter.rb +3 -6
  25. data/lib/daedal/filters/terms_filter.rb +3 -6
  26. data/lib/daedal/queries/bool_query.rb +8 -11
  27. data/lib/daedal/queries/constant_score_query.rb +4 -8
  28. data/lib/daedal/queries/dis_max_query.rb +5 -9
  29. data/lib/daedal/queries/filtered_query.rb +3 -8
  30. data/lib/daedal/queries/fuzzy_query.rb +24 -0
  31. data/lib/daedal/queries/match_all_query.rb +1 -3
  32. data/lib/daedal/queries/match_query.rb +11 -15
  33. data/lib/daedal/queries/multi_match_query.rb +12 -16
  34. data/lib/daedal/queries/nested_query.rb +7 -10
  35. data/lib/daedal/queries/prefix_query.rb +7 -9
  36. data/lib/daedal/queries/{base_query.rb → query.rb} +1 -4
  37. data/lib/daedal/queries/query_string_query.rb +32 -0
  38. data/lib/daedal/version.rb +1 -1
  39. data/spec/spec_helper.rb +4 -2
  40. data/spec/unit/daedal/filters/and_filter_spec.rb +0 -1
  41. data/spec/unit/daedal/filters/bool_filter_spec.rb +89 -0
  42. data/spec/unit/daedal/filters/geo_distance_filter_spec.rb +0 -1
  43. data/spec/unit/daedal/filters/or_filter_spec.rb +74 -0
  44. data/spec/unit/daedal/filters/range_filter_spec.rb +0 -1
  45. data/spec/unit/daedal/filters/term_filter_spec.rb +0 -1
  46. data/spec/unit/daedal/filters/terms_filter_spec.rb +4 -2
  47. data/spec/unit/daedal/queries/bool_query_spec.rb +1 -3
  48. data/spec/unit/daedal/queries/constant_score_query_spec.rb +0 -2
  49. data/spec/unit/daedal/queries/dis_max_query_spec.rb +1 -2
  50. data/spec/unit/daedal/queries/filtered_query_spec.rb +1 -3
  51. data/spec/unit/daedal/queries/fuzzy_query_spec.rb +89 -0
  52. data/spec/unit/daedal/queries/match_all_query_spec.rb +0 -1
  53. data/spec/unit/daedal/queries/match_query_spec.rb +2 -3
  54. data/spec/unit/daedal/queries/multi_match_query_spec.rb +2 -3
  55. data/spec/unit/daedal/queries/nested_query_spec.rb +0 -2
  56. data/spec/unit/daedal/queries/prefix_query_spec.rb +0 -1
  57. data/spec/unit/daedal/queries/query_string_spec.rb +296 -0
  58. metadata +18 -7
  59. data/lib/daedal/attributes.rb +0 -15
  60. data/lib/daedal/filters.rb +0 -11
  61. data/lib/daedal/queries.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 591b82d1a7aec22b940c410fd2d5afe79877e24f
4
- data.tar.gz: 16e8916ccff2aef76cc75f1052085ffe3d08527f
3
+ metadata.gz: c847bcafde8c2364dd1105418bf51ddb0f6ecd42
4
+ data.tar.gz: 4abb328be7b9473dec47854db2e1207cce6589e9
5
5
  SHA512:
6
- metadata.gz: f0a6a7d9a161c54625c7dffd3ed1040ba7aee46e13b960ce5caaf56b0be2afa24bfb4dbd5ab9f6b2f2d0a81ee58fa51d4db03c1f4fe324644360dfc930dca525
7
- data.tar.gz: e4bc1ce204ce207255e1ebd1c5c1311fd80744fcd323cd737fce6e5fd2ffeb7d1150700d881124576d11fb738e1056a8d16835dbd34b00548429acd432e46527
6
+ metadata.gz: 50cd4b1ab8720509f8b38a7968b2e1f3258d75c7fd79a3771ddf12390210e1d13d0afcbf72fe961d12d75eba477e719922e53cc17feca06fe6a94b51200d89b6
7
+ data.tar.gz: cab1fa56a98d7f0c3380d57af1e0a96c027235080a19ad3db38818127f610103633fb91e61169ff63ccc24c9fc1a53c406dcf96f31a11a9101872d3e6e3599d2
data/.gitignore CHANGED
@@ -11,4 +11,11 @@
11
11
  # Ignore all logfiles and tempfiles.
12
12
  /log/*.log
13
13
  /tmp
14
- *.swp
14
+ *.swp
15
+
16
+ # Ignore coverage stuff
17
+ /coverage
18
+ /.coveralls.yml
19
+
20
+ # Ignore gem builds
21
+ *.gem
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ notifications:
5
+ email:
6
+ - cas13091@gmail.com
7
+ script: "bundle exec rspec"
data/Gemfile CHANGED
@@ -1,9 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rspec'
4
- gem 'guard'
5
- gem 'guard-rspec'
6
- gem 'require_all'
7
- gem 'fuubar'
8
- gem 'debugger'
9
- gem 'virtus', '>= 1.0.0'
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'rspec'
7
+ gem 'coveralls'
8
+ gem 'guard'
9
+ gem 'guard-rspec'
10
+ gem 'fuubar'
11
+ end
@@ -1,3 +1,9 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ daedal (0.0.4)
5
+ virtus (>= 1.0.0)
6
+
1
7
  GEM
2
8
  remote: https://rubygems.org/
3
9
  specs:
@@ -5,64 +11,74 @@ GEM
5
11
  descendants_tracker (~> 0.0.1)
6
12
  ice_nine (~> 0.9)
7
13
  backports (3.3.5)
8
- coderay (1.0.9)
14
+ celluloid (0.15.2)
15
+ timers (~> 1.1.0)
16
+ coderay (1.1.0)
9
17
  coercible (0.2.0)
10
18
  backports (~> 3.0, >= 3.1.0)
11
19
  descendants_tracker (~> 0.0.1)
12
- columnize (0.3.6)
13
- debugger (1.6.2)
14
- columnize (>= 0.3.1)
15
- debugger-linecache (~> 1.2.0)
16
- debugger-ruby_core_source (~> 1.2.3)
17
- debugger-linecache (1.2.0)
18
- debugger-ruby_core_source (1.2.3)
20
+ coveralls (0.7.0)
21
+ multi_json (~> 1.3)
22
+ rest-client
23
+ simplecov (>= 0.7)
24
+ term-ansicolor
25
+ thor
19
26
  descendants_tracker (0.0.3)
20
- diff-lcs (1.2.4)
27
+ diff-lcs (1.2.5)
21
28
  equalizer (0.0.8)
22
- ffi (1.9.0)
29
+ ffi (1.9.3)
23
30
  formatador (0.2.4)
24
31
  fuubar (1.2.1)
25
32
  rspec (~> 2.0)
26
33
  rspec-instafail (~> 0.2.0)
27
34
  ruby-progressbar (~> 1.0)
28
- guard (1.8.3)
35
+ guard (2.2.4)
29
36
  formatador (>= 0.2.4)
30
- listen (~> 1.3)
31
- lumberjack (>= 1.0.2)
32
- pry (>= 0.9.10)
33
- thor (>= 0.14.6)
34
- guard-rspec (3.0.2)
35
- guard (>= 1.8)
36
- rspec (~> 2.13)
37
+ listen (~> 2.1)
38
+ lumberjack (~> 1.0)
39
+ pry (>= 0.9.12)
40
+ thor (>= 0.18.1)
41
+ guard-rspec (4.2.0)
42
+ guard (>= 2.1.1)
43
+ rspec (>= 2.14, < 4.0)
37
44
  ice_nine (0.10.0)
38
- listen (1.3.1)
45
+ listen (2.4.0)
46
+ celluloid (>= 0.15.2)
39
47
  rb-fsevent (>= 0.9.3)
40
48
  rb-inotify (>= 0.9)
41
- rb-kqueue (>= 0.2)
42
49
  lumberjack (1.0.4)
43
50
  method_source (0.8.2)
44
- pry (0.9.12.2)
45
- coderay (~> 1.0.5)
51
+ mime-types (2.0)
52
+ multi_json (1.8.2)
53
+ pry (0.9.12.4)
54
+ coderay (~> 1.0)
46
55
  method_source (~> 0.8)
47
56
  slop (~> 3.4)
48
57
  rb-fsevent (0.9.3)
49
58
  rb-inotify (0.9.2)
50
59
  ffi (>= 0.5.0)
51
- rb-kqueue (0.2.0)
52
- ffi (>= 0.5.0)
53
- require_all (1.3.1)
60
+ rest-client (1.6.7)
61
+ mime-types (>= 1.16)
54
62
  rspec (2.14.1)
55
63
  rspec-core (~> 2.14.0)
56
64
  rspec-expectations (~> 2.14.0)
57
65
  rspec-mocks (~> 2.14.0)
58
- rspec-core (2.14.5)
59
- rspec-expectations (2.14.2)
66
+ rspec-core (2.14.7)
67
+ rspec-expectations (2.14.4)
60
68
  diff-lcs (>= 1.1.3, < 2.0)
61
69
  rspec-instafail (0.2.4)
62
- rspec-mocks (2.14.3)
70
+ rspec-mocks (2.14.4)
63
71
  ruby-progressbar (1.2.0)
64
- slop (3.4.6)
72
+ simplecov (0.7.1)
73
+ multi_json (~> 1.0)
74
+ simplecov-html (~> 0.7.1)
75
+ simplecov-html (0.7.1)
76
+ slop (3.4.7)
77
+ term-ansicolor (1.2.2)
78
+ tins (~> 0.8)
65
79
  thor (0.18.1)
80
+ timers (1.1.0)
81
+ tins (0.13.1)
66
82
  virtus (1.0.0)
67
83
  axiom-types (~> 0.0.5)
68
84
  coercible (~> 0.2)
@@ -73,10 +89,9 @@ PLATFORMS
73
89
  ruby
74
90
 
75
91
  DEPENDENCIES
76
- debugger
92
+ coveralls
93
+ daedal!
77
94
  fuubar
78
95
  guard
79
96
  guard-rspec
80
- require_all
81
97
  rspec
82
- virtus (>= 1.0.0)
data/README.md CHANGED
@@ -1,79 +1,109 @@
1
1
  Daedal
2
2
  ======
3
+ [![Build Status](https://travis-ci.org/cschuch/daedal.png?branch=master)](https://travis-ci.org/cschuch/daedal)
4
+ [![Coverage Status](https://coveralls.io/repos/cschuch/daedal/badge.png)](https://coveralls.io/r/cschuch/daedal)
5
+ [![Gem Version](https://badge.fury.io/rb/daedal.png)](http://badge.fury.io/rb/daedal)
3
6
 
4
7
  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
+ query creation simpler and easier to debug. Type checking and attribute
8
9
  coercion are handled using [Virtus](https://github.com/solnic/virtus) to make
9
10
  it harder to construct invalid ElasticSearch queries before sending them to the server.
10
11
 
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 :)
12
+ The ElasticSearch [Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html)
13
+ has a tremendous amount of flexibility, allowing users to finely tune their search results.
14
+ However, elaborate queries often take the form of a complex, deeply nested hash,
15
+ which can become difficult to create or traverse. By wrapping the core components of the
16
+ query DSL into Ruby objects, Daedal addresses the following issues:
17
+
18
+ * Constructing a large nested hash can be a headache, and using tools like `Hashie` may result in performance issues
19
+ * Remembering all the optional parameters each query can take, where they reside within the query structure, and what values they can take can be challenging
20
+ * Improperly structured queries, or queries with bad parameters, are hard to catch before sending to the server (and receiving an error)
21
+ * Debugging invalid queries can be a grueling task
22
+
23
+ Daedal also makes it easy to define custom queries tailored to your specific use case - you can see
24
+ a simple example at the end of the documentation.
15
25
 
16
26
  Installation
17
27
  ------------
18
28
 
29
+ From the terminal:
19
30
  ``` terminal
20
31
  $ gem install daedal
21
32
  ```
22
33
 
23
- or in your `Gemfile`
34
+ or in your `Gemfile`:
24
35
 
25
36
  ``` ruby
26
37
  gem 'daedal'
27
38
  ```
28
39
 
40
+ Then, it's as simple as including the line:
41
+
42
+ ``` ruby
43
+ require 'daedal'
44
+ ```
45
+
29
46
  Usage
30
47
  --------
31
48
 
49
+ See the [Daedal Wiki](https://github.com/cschuch/daedal/wiki) for some examples.
50
+
32
51
  ### ElasticSearch Query DSL
33
52
 
34
53
  Other Ruby packages for ElasticSearch allow you to create queries either as
35
54
  hashes or by constructing raw JSON:
36
55
 
37
56
  ``` ruby
38
- match_query = {'match' => {'foo' => {'query' => 'bar'}}}
57
+ author_query = {'match' => {'author' => {'query' => 'Beckett'}}}
39
58
  ```
40
59
 
41
- For more complicated queries, dealing with the resulting large nested hash can be
42
- frustrating. Inspired by ElasticSearch's built in
60
+ For simple queries like the example above, this works just fine. However, as queries become
61
+ more complicated, the hash can quickly take on a life of its own. Inspired by ElasticSearch's
43
62
  [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.
63
+ Daedal contains Ruby classes designed to make query construction more manageable.
45
64
 
46
65
  ### Queries
47
66
 
48
- Queries are contained within the `Queries` module. You can construct query components like:
67
+ Queries are contained within the `Daedal::Queries` module. You can construct query components like:
49
68
 
50
69
  ``` ruby
51
- require 'daedal'
52
-
53
- # creates the basic match query
54
- match_query = Daedal::Queries::MatchQuery.new(field: 'foo', query: 'bar')
70
+ author_query = Daedal::Queries::MatchQuery.new(field: 'author', query: 'Beckett')
55
71
  ```
56
- Each query object has `#to_json` defined for easy conversion for use with any of the Ruby
72
+
73
+ Each query has `#to_json` defined for easy conversion for use with any of the Ruby
57
74
  ElasticSearch clients out there:
75
+
58
76
  ``` ruby
59
- match_query.to_json # => "{\"match\":{\"foo\":{\"query\":\"bar\"}}}"
77
+ author_query.to_json # => "{\"match\":{\"author\":{\"query\":\"Beckett\"}}}"
60
78
  ```
61
79
 
62
- To date (12/8/2013), I have implemented the following queries:
80
+ The benefits of using Daedal become more obvious for aggregate queries such as the `bool query`:
81
+
82
+ ``` ruby
83
+ bool_query = Daedal::Queries::BoolQuery.new(must: [author_query])
84
+ bool_query.to_json # => "{\"bool\":{\"should\":[],\"must\":[{\"match\":{\"author\":{\"query\":\"Beckett\"}}}],\"must_not\":[]}}"
85
+
86
+ lines_query = Daedal::Queries::MatchQuery.new(field: 'lines', query: "We're waiting for Godot")
87
+ bool_query.should << lines_query
88
+
89
+ bool_query.to_json # => "{\"bool\":{\"should\":[{\"match\":{\"lines\":{\"query\":\"We're waiting for Godot\"}}}],\"must\":[{\"match\":{\"author\":{\"query\":\"Beckett\"}}}],\"must_not\":[]}}"
90
+ ```
91
+
92
+ Currently, the following queries have been implemented:
63
93
  * [bool query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)
64
94
  * [constant score query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html)
65
95
  * [dis max query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html)
66
96
  * [filtered query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html)
97
+ * [fuzzy query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html)
67
98
  * [match all query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html)
68
99
  * [match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-query.html)
69
100
  * [multi match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html)
70
101
  * [nested query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html)
71
102
  * [prefix query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html)
103
+ * [query string query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html)
72
104
 
73
- To be implemented next:
105
+ On deck:
74
106
  * [function score query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html)
75
- * [fuzzy query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html)
76
- * [query string query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html)
77
107
  * [range query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-range-query.html)
78
108
  * [regexp query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html)
79
109
  * [term query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-query.html)
@@ -89,28 +119,26 @@ Queries I'm not planning on implementing at all, since they're deprecated:
89
119
 
90
120
  ### Filters
91
121
 
92
- Filters are contained within the `Filters` module. You can construct filter components
122
+ Filters are contained within the `Daedal::Filters` module. You can construct filter components
93
123
  in the same way as queries:
94
124
 
95
125
  ``` ruby
96
- require 'daedal'
97
-
98
- term_filter = Daedal::Filters::TermFilter.new(field: 'foo', term: 'bar')
126
+ term_filter = Daedal::Filters::TermFilter.new(field: 'characters', term: 'Pozzo')
99
127
 
100
- term_filter.to_json # => "{\"term\":{\"foo\":\"bar\"}}"
128
+ term_filter.to_json # => "{\"term\":{\"characters\":\"Pozzo\"}}"
101
129
  ```
102
130
 
103
- To date (12/8/2013), I have implemented the following filters:
131
+ Currently, the following filters have been implemented:
104
132
  * [and filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html)
133
+ * [bool filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html)
105
134
  * [geo distance filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-filter.html)
135
+ * [or filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html)
106
136
  * [range filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-range-filter.html)
107
137
  * [term filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-filter.html)
108
138
  * [terms filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html)
109
139
 
110
- To be implemented next:
111
- * [bool filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html)
140
+ On deck:
112
141
  * [nested filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-nested-filter.html)
113
- * [or filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html)
114
142
 
115
143
  ### Type checking and attribute coercion
116
144
 
@@ -125,54 +153,85 @@ constant_score_query = {'constant_score' => {'boost' => 'foo', 'query' => {'matc
125
153
  would yield a server error, since the `boost` parameter must be a number.
126
154
 
127
155
  Daedal uses [Virtus](https://github.com/solnic/virtus) to perform data-type coercions.
128
- That way, invalid query parameters are surfaced at runtime, making debugging easier.
129
- The previous `constant_score_query` example in Daedal would raise an error:
156
+ Invalid query parameters are surfaced at runtime, making debugging much easier.
157
+ The previous example in Daedal would raise an error:
130
158
 
131
159
  ``` ruby
132
- match_all_query = Daedal::Queries::MatchAllQuery.new()
133
- constant_score_query = Daedal::Queries::ConstantScoreQuery.new(boost: 'foo', query: match_all_query)
160
+ match_all_query = Daedal::Queries::MatchAllQuery.new
134
161
 
162
+ constant_score_query = Daedal::Queries::ConstantScoreQuery.new(boost: 'foo', query: match_all_query)
135
163
  # Virtus::CoercionError: Failed to coerce "foo" into Float
136
164
  ```
137
165
 
138
- ### Creating your own queries
166
+ Similarly, trying to add non-queries to an aggregate query like the `bool` or `dis max` queries
167
+ will result in an error:
139
168
 
140
- Currently, I've only made it through a fraction of the entire Query DSL, but will be working to
141
- achieve complete coverage as quickly as possible. If you need to use a query that
142
- I haven't gotten to yet, or if you want to create your own more specialized queries within
143
- your own project, defining the query classes is relatively straightforward - just make
144
- your new class a sublass of the `Daedal::Queries::BaseQuery` or `Daedal::Filters::BaseFilter`
145
- classes, and define the `to_hash` method. All methods made available by including `Virtus.model` in your
146
- class will be available to you, as well.
169
+ ``` ruby
170
+ dis_max_query = Daedal::Queries::DisMaxQuery.new
171
+
172
+ dis_max_query.queries << :foo
173
+ # Virtus::CoercionError: Failed to coerce :foo into "Daedal::Queries::Query"
174
+ ```
147
175
 
148
- Example:
176
+ ### Creating custom queries
177
+
178
+ Currently, I've only made it through a fraction of the entire Query DSL, but will be adding more
179
+ as time goes by. If there's a component of the query DSL that you need that isn't implemented yet,
180
+ it's easy to define it yourself within your project (or, feel free to contribute to Daedal!).
181
+
182
+ Creating custom filters or queries tailored specifically to your use case is also pretty straightforward.
183
+ Here are some guidelines:
184
+
185
+ * Make your class inherit from `Daedal::Queries::Query` or `Daedal::Filters::Filter`
186
+ * Define the parameters for your query using [Virtus](https://github.com/solnic/virtus) attributes (**note**: `strict` coercion is being used)
187
+ * Define the `#to_hash` method
188
+
189
+ Example of a custom query:
149
190
  ``` ruby
150
- class MyQuery < Daedal::Queries::BaseQuery
191
+ class PlayQuery < Daedal::Queries::Query
151
192
 
152
- # define the attributes that you need in your query
153
- attribute :foo, String
154
- attribute :bar, String
193
+ # define the parameters that you want in your query
194
+ # if the field is optional, make sure to set required to false
195
+ attribute :author, String
196
+
197
+ attribute :characters, Array[String], required: false
198
+ attribute :title, String, required: false
199
+
200
+ def construct_query
201
+ author_query = Daedal::Queries::MatchQuery.new(field: 'author', query: author)
202
+ title_query = Daedal::Queries::MatchQuery.new(field: 'title', query: title)
203
+
204
+ full_query = Daedal::Queries::BoolQuery.new(must: [author_query], should: [title_query])
205
+ characters.each do |character|
206
+ full_query.should << Daedal::Queries::MatchQuery.new(field: 'characters', query: character)
207
+ end
208
+
209
+ full_query
210
+ end
155
211
 
156
212
  # define the to_hash method to convert for use in ElasticSearch
157
213
  def to_hash
158
- ...
214
+ construct_query.to_hash
159
215
  end
160
216
  end
217
+
218
+ play_query = PlayQuery.new(author: 'Beckett', title: 'Waiting for Godot', characters: ['Estragon', 'Vladimir'])
219
+ puts play_query.to_json # => {"bool":{"should":[{"match":{"title":{"query":"Waiting for Godot"}}},{"match":{"characters":{"query":"Estragon"}}},{"match":{"characters":{"query":"Vladimir"}}}],"must":[{"match":{"author":{"query":"Beckett"}}}],"must_not":[]}}
161
220
  ```
162
221
 
163
222
  Contributing
164
223
  -------------
165
224
 
166
- The ElasticSearch Query DSL is pretty large and includes a ton of nuance. I'm starting with the
225
+ The ElasticSearch Query DSL is pretty big and includes a ton of nuance. I'm starting with the
167
226
  most basic parts of the DSL (and the parts I use for work), so if you want to help out with the project
168
227
  to meet your needs please feel free to contribute! I just ask that you:
169
228
 
170
- * Fork the project.
171
- * Make your changes or additions.
172
- * Add tests! My goal is complete test coverage, so please take the effort to make them pretty comprehensive.
173
- * Send me a pull request.
229
+ * Fork the project
230
+ * Make your changes or additions
231
+ * Add tests! My goal is to keep Daedal a thoroughly tested project
232
+ * Send me a pull request
174
233
 
175
- Feedback or suggestions are also always welcome.
234
+ Feedback or suggestions are also always welcome!
176
235
 
177
236
  License
178
237
  -------