daedal 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +29 -1
- data/daedal.gemspec +1 -1
- data/lib/daedal/attributes.rb +5 -0
- data/lib/daedal/attributes/distance_unit.rb +15 -0
- data/lib/daedal/attributes/filter.rb +13 -0
- data/lib/daedal/attributes/filter_array.rb +24 -0
- data/lib/daedal/attributes/lower_case_string.rb +14 -0
- data/lib/daedal/attributes/query.rb +13 -0
- data/lib/daedal/attributes/query_array.rb +2 -0
- data/lib/daedal/filters.rb +3 -0
- data/lib/daedal/filters/and_filter.rb +21 -0
- data/lib/daedal/filters/base_filter.rb +1 -1
- data/lib/daedal/filters/geo_distance_filter.rb +27 -0
- data/lib/daedal/filters/range_filter.rb +27 -0
- data/lib/daedal/queries.rb +1 -0
- data/lib/daedal/queries/bool_query.rb +5 -4
- data/lib/daedal/queries/constant_score_query.rb +2 -2
- data/lib/daedal/queries/dis_max_query.rb +3 -2
- data/lib/daedal/queries/filtered_query.rb +2 -2
- data/lib/daedal/queries/match_query.rb +2 -1
- data/lib/daedal/queries/nested_query.rb +4 -4
- data/lib/daedal/queries/prefix_query.rb +25 -0
- data/lib/daedal/version.rb +3 -0
- data/spec/unit/daedal/filters/and_filter_spec.rb +87 -0
- data/spec/unit/daedal/filters/geo_distance_filter_spec.rb +104 -0
- data/spec/unit/daedal/filters/range_filter_spec.rb +90 -0
- data/spec/unit/daedal/filters/term_filter_spec.rb +3 -3
- data/spec/unit/daedal/filters/terms_filter_spec.rb +2 -2
- data/spec/unit/daedal/queries/bool_query_spec.rb +42 -4
- data/spec/unit/daedal/queries/constant_score_query_spec.rb +3 -3
- data/spec/unit/daedal/queries/dis_max_query_spec.rb +18 -2
- data/spec/unit/daedal/queries/filtered_query_spec.rb +3 -3
- data/spec/unit/daedal/queries/match_query_spec.rb +36 -8
- data/spec/unit/daedal/queries/multi_match_query_spec.rb +8 -8
- data/spec/unit/daedal/queries/nested_query_spec.rb +4 -4
- data/spec/unit/daedal/queries/prefix_query_spec.rb +85 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 591b82d1a7aec22b940c410fd2d5afe79877e24f
|
4
|
+
data.tar.gz: 16e8916ccff2aef76cc75f1052085ffe3d08527f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0a6a7d9a161c54625c7dffd3ed1040ba7aee46e13b960ce5caaf56b0be2afa24bfb4dbd5ab9f6b2f2d0a81ee58fa51d4db03c1f4fe324644360dfc930dca525
|
7
|
+
data.tar.gz: e4bc1ce204ce207255e1ebd1c5c1311fd80744fcd323cd737fce6e5fd2ffeb7d1150700d881124576d11fb738e1056a8d16835dbd34b00548429acd432e46527
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -67,6 +67,25 @@ To date (12/8/2013), I have implemented the following queries:
|
|
67
67
|
* [match all query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html)
|
68
68
|
* [match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-query.html)
|
69
69
|
* [multi match query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html)
|
70
|
+
* [nested query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html)
|
71
|
+
* [prefix query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html)
|
72
|
+
|
73
|
+
To be implemented next:
|
74
|
+
* [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
|
+
* [range query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-range-query.html)
|
78
|
+
* [regexp query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html)
|
79
|
+
* [term query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-query.html)
|
80
|
+
* [terms query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html)
|
81
|
+
* [wildcard query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html)
|
82
|
+
|
83
|
+
Queries I'm not planning on implementing at all, since they're deprecated:
|
84
|
+
* [custom filters score query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-custom-filters-score-query.html)
|
85
|
+
* [custom score query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-custom-score-query.html)
|
86
|
+
* [custom boost factor query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-custom-boost-factor-query.html)
|
87
|
+
* [text query](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-text-query.html)
|
88
|
+
|
70
89
|
|
71
90
|
### Filters
|
72
91
|
|
@@ -82,7 +101,16 @@ term_filter.to_json # => "{\"term\":{\"foo\":\"bar\"}}"
|
|
82
101
|
```
|
83
102
|
|
84
103
|
To date (12/8/2013), I have implemented the following filters:
|
104
|
+
* [and filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html)
|
105
|
+
* [geo distance filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-filter.html)
|
106
|
+
* [range filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-range-filter.html)
|
85
107
|
* [term filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-filter.html)
|
108
|
+
* [terms filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html)
|
109
|
+
|
110
|
+
To be implemented next:
|
111
|
+
* [bool filter](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html)
|
112
|
+
* [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)
|
86
114
|
|
87
115
|
### Type checking and attribute coercion
|
88
116
|
|
@@ -91,7 +119,7 @@ assign an invalid value to a specific field, which would then result in
|
|
91
119
|
an error response when sending the query to the server. For instance, the query:
|
92
120
|
|
93
121
|
``` ruby
|
94
|
-
constant_score_query = {'constant_score' => {'boost' => 'foo', 'query'
|
122
|
+
constant_score_query = {'constant_score' => {'boost' => 'foo', 'query' => {'match_all' => {}}}}
|
95
123
|
```
|
96
124
|
|
97
125
|
would yield a server error, since the `boost` parameter must be a number.
|
data/daedal.gemspec
CHANGED
data/lib/daedal/attributes.rb
CHANGED
@@ -2,7 +2,12 @@ require 'virtus'
|
|
2
2
|
require 'daedal/attributes/operator'
|
3
3
|
require 'daedal/attributes/match_type'
|
4
4
|
require 'daedal/attributes/query_array'
|
5
|
+
require 'daedal/attributes/filter_array'
|
5
6
|
require 'daedal/attributes/score_mode'
|
7
|
+
require 'daedal/attributes/lower_case_string'
|
8
|
+
require 'daedal/attributes/distance_unit'
|
9
|
+
require 'daedal/attributes/query'
|
10
|
+
require 'daedal/attributes/filter'
|
6
11
|
|
7
12
|
module Daedal
|
8
13
|
module Attributes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Daedal
|
2
|
+
module Attributes
|
3
|
+
"""Custom coercer for the type attribute"""
|
4
|
+
class DistanceUnit < Virtus::Attribute
|
5
|
+
ALLOWED_DISTANCE_UNITS = ['mi', 'km']
|
6
|
+
def coerce(value)
|
7
|
+
if value.nil? or !ALLOWED_DISTANCE_UNITS.include? value.to_s
|
8
|
+
raise Virtus::CoercionError.new(value, 'Daedal::Attributes::DistanceUnit')
|
9
|
+
end
|
10
|
+
|
11
|
+
value.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Daedal
|
2
|
+
module Attributes
|
3
|
+
class Filter < Virtus::Attribute
|
4
|
+
def coerce(f)
|
5
|
+
unless f.is_a? Daedal::Filters::BaseFilter or !required? && f.nil?
|
6
|
+
raise Virtus::CoercionError.new(f, 'Daedal::Filters::BaseFilter')
|
7
|
+
end
|
8
|
+
|
9
|
+
f
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Daedal
|
2
|
+
module Attributes
|
3
|
+
"""Custom attribute for an array of queries"""
|
4
|
+
class FilterArray < Array
|
5
|
+
# override the << method so that you throw
|
6
|
+
# an error if you don't try to append a query
|
7
|
+
def <<(f)
|
8
|
+
if f.is_a? Daedal::Filters::BaseFilter
|
9
|
+
super f
|
10
|
+
else
|
11
|
+
raise Virtus::CoercionError.new(f, 'Daedal::Filters::BaseFilter')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def unshift(f)
|
16
|
+
if f.is_a? Daedal::Filters::BaseFilter
|
17
|
+
super f
|
18
|
+
else
|
19
|
+
raise Virtus::CoercionError.new(f, 'Daedal::Filters::BaseFilter')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Daedal
|
2
|
+
module Attributes
|
3
|
+
"""Custom coercer for the type attribute"""
|
4
|
+
class LowerCaseString < Virtus::Attribute
|
5
|
+
def coerce(value)
|
6
|
+
value = value.to_s
|
7
|
+
if value.empty?
|
8
|
+
raise Virtus::CoercionError.new(value, 'Daedal::Attributes::LowerCaseString')
|
9
|
+
end
|
10
|
+
value.downcase
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Daedal
|
2
|
+
module Attributes
|
3
|
+
class Query < Virtus::Attribute
|
4
|
+
def coerce(q)
|
5
|
+
unless q.is_a? Daedal::Queries::BaseQuery or !required? && q.nil?
|
6
|
+
raise Virtus::CoercionError.new(q, 'Daedal::Queries::BaseQuery')
|
7
|
+
end
|
8
|
+
|
9
|
+
q
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -2,8 +2,10 @@ module Daedal
|
|
2
2
|
module Attributes
|
3
3
|
"""Custom attribute for an array of queries"""
|
4
4
|
class QueryArray < Array
|
5
|
+
|
5
6
|
# override the << method so that you throw
|
6
7
|
# an error if you don't try to append a query
|
8
|
+
|
7
9
|
def <<(q)
|
8
10
|
if q.is_a? Daedal::Queries::BaseQuery
|
9
11
|
super q
|
data/lib/daedal/filters.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'daedal/filters/base_filter'
|
2
2
|
require 'daedal/filters/term_filter'
|
3
3
|
require 'daedal/filters/terms_filter'
|
4
|
+
require 'daedal/filters/range_filter'
|
5
|
+
require 'daedal/filters/geo_distance_filter'
|
6
|
+
require 'daedal/filters/and_filter'
|
4
7
|
|
5
8
|
module Daedal
|
6
9
|
module Filters
|
@@ -0,0 +1,21 @@
|
|
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 AndFilter < BaseFilter
|
8
|
+
|
9
|
+
# required attributes
|
10
|
+
attribute :filters, Attributes::FilterArray
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
unless filters.empty?
|
14
|
+
{:and => filters.map {|f| f.to_hash}}
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
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 GeoDistanceFilter < BaseFilter
|
8
|
+
|
9
|
+
# required attributes
|
10
|
+
attribute :field, Symbol
|
11
|
+
attribute :lat, Float
|
12
|
+
attribute :lon, Float
|
13
|
+
attribute :distance, Float
|
14
|
+
|
15
|
+
# non required attributes
|
16
|
+
attribute :unit, Attributes::DistanceUnit, default: 'km'
|
17
|
+
|
18
|
+
def full_distance
|
19
|
+
"#{distance}#{unit}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
{geo_distance: {distance: full_distance, field => {lat: lat, lon: lon}}}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'daedal/filters/base_filter'
|
2
|
+
|
3
|
+
module Daedal
|
4
|
+
module Filters
|
5
|
+
"""Class for the basic term filter"""
|
6
|
+
class RangeFilter < BaseFilter
|
7
|
+
|
8
|
+
# required attributes
|
9
|
+
attribute :field, Symbol
|
10
|
+
attribute :gte
|
11
|
+
attribute :lte
|
12
|
+
attribute :gt
|
13
|
+
attribute :lt
|
14
|
+
|
15
|
+
def initialize(options={})
|
16
|
+
super options
|
17
|
+
unless !gte.nil? or !gt.nil? or !lt.nil? or !lte.nil?
|
18
|
+
raise "Must give at least one of gte, gt, lt, or lte"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
{range: {field => {gte: gte, lte: lte, lt: lt, gt: gt}.select {|k,v| !v.nil?}}}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/daedal/queries.rb
CHANGED
@@ -10,18 +10,19 @@ module Daedal
|
|
10
10
|
|
11
11
|
# should, must, and must_not must be an array of queries
|
12
12
|
# these queries must inherit from the BaseQuery class
|
13
|
-
attribute :should, Attributes::QueryArray
|
14
|
-
attribute :must, Attributes::QueryArray
|
15
|
-
attribute :must_not, Attributes::QueryArray
|
13
|
+
attribute :should, Attributes::QueryArray, default: Array.new
|
14
|
+
attribute :must, Attributes::QueryArray, default: Array.new
|
15
|
+
attribute :must_not, Attributes::QueryArray, default: Array.new
|
16
16
|
|
17
17
|
# non required attributes
|
18
18
|
attribute :minimum_should_match, Integer, required: false
|
19
19
|
attribute :boost, Integer, required: false
|
20
20
|
attribute :name, Symbol, required: false
|
21
|
+
attribute :disable_coord, Boolean, required: false
|
21
22
|
|
22
23
|
def to_hash
|
23
24
|
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}}}
|
24
|
-
options = {minimum_should_match: minimum_should_match, boost: boost, _name: name}
|
25
|
+
options = {minimum_should_match: minimum_should_match, boost: boost, _name: name, disable_coord: disable_coord}
|
25
26
|
result[:bool].merge!(options.select { |k,v| !v.nil? })
|
26
27
|
|
27
28
|
result
|
@@ -11,8 +11,8 @@ module Daedal
|
|
11
11
|
attribute :boost, Float
|
12
12
|
|
13
13
|
# non required attributes, but one must be required of the two
|
14
|
-
attribute :query,
|
15
|
-
attribute :filter,
|
14
|
+
attribute :query, Attributes::Query, required: false
|
15
|
+
attribute :filter, Attributes::Filter, required: false
|
16
16
|
|
17
17
|
# you must require *one of* query or filter in order for this to be valid
|
18
18
|
def initialize(options={})
|
@@ -8,15 +8,16 @@ module Daedal
|
|
8
8
|
class DisMaxQuery < BaseQuery
|
9
9
|
|
10
10
|
# required attributes
|
11
|
-
attribute :queries, Attributes::QueryArray
|
11
|
+
attribute :queries, Attributes::QueryArray, 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
|
+
attribute :name, Symbol, required: false
|
16
17
|
|
17
18
|
def to_hash
|
18
19
|
result = {dis_max: {queries: queries.map {|q| q.to_hash }}}
|
19
|
-
options = {tie_breaker: tie_breaker, boost: boost}
|
20
|
+
options = {tie_breaker: tie_breaker, boost: boost, _name: name}
|
20
21
|
result[:dis_max].merge!(options.select { |k,v| !v.nil? })
|
21
22
|
|
22
23
|
result
|
@@ -9,8 +9,8 @@ module Daedal
|
|
9
9
|
class FilteredQuery < BaseQuery
|
10
10
|
|
11
11
|
# required attributes
|
12
|
-
attribute :query,
|
13
|
-
attribute :filter,
|
12
|
+
attribute :query, Attributes::Query, default: Daedal::Queries::MatchAllQuery.new
|
13
|
+
attribute :filter, Attributes::Filter, default: Daedal::Filters::BaseFilter.new
|
14
14
|
|
15
15
|
def to_hash
|
16
16
|
{filtered: {query: query.to_hash, filter: filter.to_hash}}
|
@@ -19,11 +19,12 @@ module Daedal
|
|
19
19
|
attribute :analyzer, Symbol, required: false
|
20
20
|
attribute :boost, Integer, required: false
|
21
21
|
attribute :fuzziness, Float, required: false
|
22
|
+
attribute :slop, Integer, required: false
|
22
23
|
|
23
24
|
def to_hash
|
24
25
|
|
25
26
|
result = {match: {field => {query: query}}}
|
26
|
-
options = {minimum_should_match: minimum_should_match, cutoff_frequency: cutoff_frequency, type: type, analyzer: analyzer, boost: boost, fuzziness: fuzziness, operator: operator}
|
27
|
+
options = {minimum_should_match: minimum_should_match, cutoff_frequency: cutoff_frequency, type: type, analyzer: analyzer, boost: boost, fuzziness: fuzziness, operator: operator, slop: slop}
|
27
28
|
result[:match][field].merge! options.select {|k,v| !v.nil?}
|
28
29
|
|
29
30
|
result
|
@@ -8,16 +8,16 @@ module Daedal
|
|
8
8
|
|
9
9
|
# required attributes
|
10
10
|
attribute :path, Symbol
|
11
|
-
attribute :query,
|
11
|
+
attribute :query, Attributes::Query
|
12
12
|
|
13
13
|
# non required attributes
|
14
14
|
attribute :score_mode, Attributes::ScoreMode, required: false
|
15
|
+
attribute :name, Symbol, required: false
|
15
16
|
|
16
17
|
def to_hash
|
17
18
|
result = {nested: {path: path, query: query.to_hash}}
|
18
|
-
|
19
|
-
|
20
|
-
end
|
19
|
+
options = {score_mode: score_mode, _name: name}
|
20
|
+
result[:nested].merge!(options.select { |k,v| !v.nil? })
|
21
21
|
|
22
22
|
result
|
23
23
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'daedal/queries/base_query'
|
2
|
+
require 'daedal/attributes'
|
3
|
+
|
4
|
+
module Daedal
|
5
|
+
module Queries
|
6
|
+
"""Class for the prefix query"""
|
7
|
+
class PrefixQuery < BaseQuery
|
8
|
+
|
9
|
+
# required attributes
|
10
|
+
attribute :field, Symbol
|
11
|
+
attribute :query, Attributes::LowerCaseString
|
12
|
+
|
13
|
+
# non required attributes
|
14
|
+
attribute :boost, Float, required: false
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
result = {prefix: {field => query}}
|
18
|
+
options = {boost: boost}
|
19
|
+
result[:prefix].merge!(options.select { |k,v| !v.nil? })
|
20
|
+
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|