elasticsearch-dsl 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +10 -19
- data/README.md +244 -15
- data/Rakefile +212 -0
- data/elasticsearch-dsl.gemspec +32 -15
- data/lib/elasticsearch-dsl.rb +1 -0
- data/lib/elasticsearch/dsl.rb +43 -3
- data/lib/elasticsearch/dsl/search.rb +241 -0
- data/lib/elasticsearch/dsl/search/aggregation.rb +79 -0
- data/lib/elasticsearch/dsl/search/aggregations/avg.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/cardinality.rb +32 -0
- data/lib/elasticsearch/dsl/search/aggregations/children.rb +39 -0
- data/lib/elasticsearch/dsl/search/aggregations/date_histogram.rb +40 -0
- data/lib/elasticsearch/dsl/search/aggregations/date_range.rb +34 -0
- data/lib/elasticsearch/dsl/search/aggregations/extended_stats.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/filter.rb +30 -0
- data/lib/elasticsearch/dsl/search/aggregations/filters.rb +35 -0
- data/lib/elasticsearch/dsl/search/aggregations/geo_bounds.rb +44 -0
- data/lib/elasticsearch/dsl/search/aggregations/geo_distance.rb +39 -0
- data/lib/elasticsearch/dsl/search/aggregations/geohash_grid.rb +35 -0
- data/lib/elasticsearch/dsl/search/aggregations/global.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/histogram.rb +35 -0
- data/lib/elasticsearch/dsl/search/aggregations/ip_range.rb +31 -0
- data/lib/elasticsearch/dsl/search/aggregations/max.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/min.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/nested.rb +34 -0
- data/lib/elasticsearch/dsl/search/aggregations/percentile_ranks.rb +34 -0
- data/lib/elasticsearch/dsl/search/aggregations/percentiles.rb +33 -0
- data/lib/elasticsearch/dsl/search/aggregations/range.rb +53 -0
- data/lib/elasticsearch/dsl/search/aggregations/reverse_nested.rb +37 -0
- data/lib/elasticsearch/dsl/search/aggregations/scripted_metric.rb +39 -0
- data/lib/elasticsearch/dsl/search/aggregations/significant_terms.rb +45 -0
- data/lib/elasticsearch/dsl/search/aggregations/stats.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/sum.rb +25 -0
- data/lib/elasticsearch/dsl/search/aggregations/terms.rb +33 -0
- data/lib/elasticsearch/dsl/search/aggregations/top_hits.rb +35 -0
- data/lib/elasticsearch/dsl/search/aggregations/value_count.rb +25 -0
- data/lib/elasticsearch/dsl/search/base_aggregation_component.rb +65 -0
- data/lib/elasticsearch/dsl/search/base_component.rb +162 -0
- data/lib/elasticsearch/dsl/search/base_compound_filter_component.rb +97 -0
- data/lib/elasticsearch/dsl/search/filter.rb +56 -0
- data/lib/elasticsearch/dsl/search/filters/and.rb +45 -0
- data/lib/elasticsearch/dsl/search/filters/bool.rb +80 -0
- data/lib/elasticsearch/dsl/search/filters/exists.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/geo_bounding_box.rb +45 -0
- data/lib/elasticsearch/dsl/search/filters/geo_distance.rb +57 -0
- data/lib/elasticsearch/dsl/search/filters/geo_distance_range.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/geo_polygon.rb +41 -0
- data/lib/elasticsearch/dsl/search/filters/geo_shape.rb +35 -0
- data/lib/elasticsearch/dsl/search/filters/geohash_cell.rb +46 -0
- data/lib/elasticsearch/dsl/search/filters/has_child.rb +73 -0
- data/lib/elasticsearch/dsl/search/filters/has_parent.rb +72 -0
- data/lib/elasticsearch/dsl/search/filters/ids.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/indices.rb +77 -0
- data/lib/elasticsearch/dsl/search/filters/limit.rb +31 -0
- data/lib/elasticsearch/dsl/search/filters/match_all.rb +29 -0
- data/lib/elasticsearch/dsl/search/filters/missing.rb +34 -0
- data/lib/elasticsearch/dsl/search/filters/nested.rb +58 -0
- data/lib/elasticsearch/dsl/search/filters/not.rb +73 -0
- data/lib/elasticsearch/dsl/search/filters/or.rb +45 -0
- data/lib/elasticsearch/dsl/search/filters/prefix.rb +29 -0
- data/lib/elasticsearch/dsl/search/filters/query.rb +54 -0
- data/lib/elasticsearch/dsl/search/filters/range.rb +39 -0
- data/lib/elasticsearch/dsl/search/filters/regexp.rb +34 -0
- data/lib/elasticsearch/dsl/search/filters/script.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/term.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/terms.rb +32 -0
- data/lib/elasticsearch/dsl/search/filters/type.rb +34 -0
- data/lib/elasticsearch/dsl/search/highlight.rb +92 -0
- data/lib/elasticsearch/dsl/search/options.rb +56 -0
- data/lib/elasticsearch/dsl/search/queries/bool.rb +75 -0
- data/lib/elasticsearch/dsl/search/queries/boosting.rb +33 -0
- data/lib/elasticsearch/dsl/search/queries/common.rb +38 -0
- data/lib/elasticsearch/dsl/search/queries/constant_score.rb +66 -0
- data/lib/elasticsearch/dsl/search/queries/dis_max.rb +35 -0
- data/lib/elasticsearch/dsl/search/queries/filtered.rb +77 -0
- data/lib/elasticsearch/dsl/search/queries/function_score.rb +102 -0
- data/lib/elasticsearch/dsl/search/queries/fuzzy.rb +45 -0
- data/lib/elasticsearch/dsl/search/queries/fuzzy_like_this.rb +37 -0
- data/lib/elasticsearch/dsl/search/queries/fuzzy_like_this_field.rb +36 -0
- data/lib/elasticsearch/dsl/search/queries/geo_shape.rb +31 -0
- data/lib/elasticsearch/dsl/search/queries/has_child.rb +57 -0
- data/lib/elasticsearch/dsl/search/queries/has_parent.rb +57 -0
- data/lib/elasticsearch/dsl/search/queries/ids.rb +28 -0
- data/lib/elasticsearch/dsl/search/queries/indices.rb +34 -0
- data/lib/elasticsearch/dsl/search/queries/match.rb +34 -0
- data/lib/elasticsearch/dsl/search/queries/match_all.rb +27 -0
- data/lib/elasticsearch/dsl/search/queries/more_like_this.rb +58 -0
- data/lib/elasticsearch/dsl/search/queries/multi_match.rb +35 -0
- data/lib/elasticsearch/dsl/search/queries/nested.rb +55 -0
- data/lib/elasticsearch/dsl/search/queries/prefix.rb +30 -0
- data/lib/elasticsearch/dsl/search/queries/query_string.rb +50 -0
- data/lib/elasticsearch/dsl/search/queries/range.rb +47 -0
- data/lib/elasticsearch/dsl/search/queries/regexp.rb +31 -0
- data/lib/elasticsearch/dsl/search/queries/simple_query_string.rb +38 -0
- data/lib/elasticsearch/dsl/search/queries/span_first.rb +28 -0
- data/lib/elasticsearch/dsl/search/queries/span_multi.rb +28 -0
- data/lib/elasticsearch/dsl/search/queries/span_near.rb +32 -0
- data/lib/elasticsearch/dsl/search/queries/span_not.rb +33 -0
- data/lib/elasticsearch/dsl/search/queries/span_or.rb +28 -0
- data/lib/elasticsearch/dsl/search/queries/span_term.rb +26 -0
- data/lib/elasticsearch/dsl/search/queries/template.rb +31 -0
- data/lib/elasticsearch/dsl/search/queries/term.rb +27 -0
- data/lib/elasticsearch/dsl/search/queries/terms.rb +27 -0
- data/lib/elasticsearch/dsl/search/queries/top_children.rb +58 -0
- data/lib/elasticsearch/dsl/search/queries/wildcard.rb +30 -0
- data/lib/elasticsearch/dsl/search/query.rb +55 -0
- data/lib/elasticsearch/dsl/search/sort.rb +50 -0
- data/lib/elasticsearch/dsl/search/suggest.rb +28 -0
- data/lib/elasticsearch/dsl/utils.rb +25 -0
- data/lib/elasticsearch/dsl/version.rb +2 -2
- data/test/integration/search_aggregation_children_test.rb +69 -0
- data/test/integration/search_aggregation_geo_test.rb +90 -0
- data/test/integration/search_aggregation_nested_test.rb +100 -0
- data/test/integration/search_aggregations_test.rb +232 -0
- data/test/integration/search_filters_test.rb +359 -0
- data/test/integration/search_options_test.rb +28 -0
- data/test/integration/search_query_test.rb +55 -0
- data/test/integration/search_size_from_test.rb +41 -0
- data/test/integration/search_sort_test.rb +36 -0
- data/test/integration/search_suggest_test.rb +62 -0
- data/test/test_helper.rb +62 -0
- data/test/unit/aggregations/avg_test.rb +24 -0
- data/test/unit/aggregations/cardinality_test.rb +40 -0
- data/test/unit/aggregations/children_test.rb +36 -0
- data/test/unit/aggregations/date_histogram_test.rb +49 -0
- data/test/unit/aggregations/date_range_test.rb +42 -0
- data/test/unit/aggregations/extended_stats_test.rb +24 -0
- data/test/unit/aggregations/filter_test.rb +31 -0
- data/test/unit/aggregations/filters_test.rb +52 -0
- data/test/unit/aggregations/geo_bounds_test.rb +37 -0
- data/test/unit/aggregations/geo_distance_test.rb +45 -0
- data/test/unit/aggregations/geohash_grid_test.rb +40 -0
- data/test/unit/aggregations/global_test.rb +20 -0
- data/test/unit/aggregations/histogram_test.rb +42 -0
- data/test/unit/aggregations/ip_range_test.rb +41 -0
- data/test/unit/aggregations/max_test.rb +24 -0
- data/test/unit/aggregations/min_test.rb +24 -0
- data/test/unit/aggregations/nested_test.rb +48 -0
- data/test/unit/aggregations/percentile_ranks_test.rb +41 -0
- data/test/unit/aggregations/percentiles_test.rb +40 -0
- data/test/unit/aggregations/range_test.rb +48 -0
- data/test/unit/aggregations/reverse_nested_test.rb +20 -0
- data/test/unit/aggregations/scripted_metric_test.rb +41 -0
- data/test/unit/aggregations/significant_terms_test.rb +46 -0
- data/test/unit/aggregations/stats_test.rb +24 -0
- data/test/unit/aggregations/sum_test.rb +24 -0
- data/test/unit/aggregations/terms_test.rb +51 -0
- data/test/unit/aggregations/top_hits_test.rb +38 -0
- data/test/unit/aggregations/value_count_test.rb +24 -0
- data/test/unit/dsl_test.rb +18 -0
- data/test/unit/filters/and_test.rb +69 -0
- data/test/unit/filters/bool_test.rb +98 -0
- data/test/unit/filters/exists_test.rb +36 -0
- data/test/unit/filters/geo_bounding_box_test.rb +45 -0
- data/test/unit/filters/geo_distance_range_test.rb +51 -0
- data/test/unit/filters/geo_distance_test.rb +58 -0
- data/test/unit/filters/geo_polygon_test.rb +36 -0
- data/test/unit/filters/geo_shape_test.rb +37 -0
- data/test/unit/filters/geohash_cell_test.rb +43 -0
- data/test/unit/filters/has_child_test.rb +52 -0
- data/test/unit/filters/has_parent_test.rb +52 -0
- data/test/unit/filters/ids_test.rb +38 -0
- data/test/unit/filters/indices_test.rb +52 -0
- data/test/unit/filters/limit_test.rb +36 -0
- data/test/unit/filters/match_all_test.rb +20 -0
- data/test/unit/filters/missing_test.rb +38 -0
- data/test/unit/filters/nested_test.rb +40 -0
- data/test/unit/filters/not_test.rb +35 -0
- data/test/unit/filters/or_test.rb +53 -0
- data/test/unit/filters/prefix_test.rb +25 -0
- data/test/unit/filters/query_test.rb +33 -0
- data/test/unit/filters/range_test.rb +47 -0
- data/test/unit/filters/regexp_test.rb +42 -0
- data/test/unit/filters/script_test.rb +38 -0
- data/test/unit/filters/term_test.rb +27 -0
- data/test/unit/filters/terms_test.rb +24 -0
- data/test/unit/filters/type_test.rb +36 -0
- data/test/unit/queries/bool_test.rb +107 -0
- data/test/unit/queries/boosting_test.rb +41 -0
- data/test/unit/queries/common_test.rb +42 -0
- data/test/unit/queries/constant_score_test.rb +47 -0
- data/test/unit/queries/dis_max_test.rb +38 -0
- data/test/unit/queries/filtered_test.rb +51 -0
- data/test/unit/queries/function_score_test.rb +70 -0
- data/test/unit/queries/fuzzy_like_this_field_test.rb +42 -0
- data/test/unit/queries/fuzzy_like_this_test.rb +44 -0
- data/test/unit/queries/fuzzy_test.rb +40 -0
- data/test/unit/queries/geo_shape_test.rb +37 -0
- data/test/unit/queries/has_child_test.rb +53 -0
- data/test/unit/queries/has_parent_test.rb +39 -0
- data/test/unit/queries/ids_test.rb +38 -0
- data/test/unit/queries/indices_test.rb +39 -0
- data/test/unit/queries/match_all_test.rb +36 -0
- data/test/unit/queries/match_test.rb +64 -0
- data/test/unit/queries/more_like_this_test.rb +53 -0
- data/test/unit/queries/multi_match_test.rb +42 -0
- data/test/unit/queries/nested_test.rb +50 -0
- data/test/unit/queries/prefix_test.rb +37 -0
- data/test/unit/queries/query_string_test.rb +55 -0
- data/test/unit/queries/range_test.rb +39 -0
- data/test/unit/queries/regexp_test.rb +43 -0
- data/test/unit/queries/simple_query_string_test.rb +43 -0
- data/test/unit/queries/span_first_test.rb +36 -0
- data/test/unit/queries/span_multi_test.rb +36 -0
- data/test/unit/queries/span_near_test.rb +39 -0
- data/test/unit/queries/span_not_test.rb +40 -0
- data/test/unit/queries/span_or_test.rb +36 -0
- data/test/unit/queries/span_term_test.rb +24 -0
- data/test/unit/queries/template_test.rb +43 -0
- data/test/unit/queries/term_test.rb +27 -0
- data/test/unit/queries/terms_test.rb +24 -0
- data/test/unit/queries/top_children_test.rb +53 -0
- data/test/unit/queries/wildcard_test.rb +43 -0
- data/test/unit/search_aggregation_test.rb +72 -0
- data/test/unit/search_base_aggregation_component_test.rb +41 -0
- data/test/unit/search_base_component_test.rb +176 -0
- data/test/unit/search_filter_test.rb +61 -0
- data/test/unit/search_highlight_test.rb +77 -0
- data/test/unit/search_options_test.rb +80 -0
- data/test/unit/search_query_test.rb +65 -0
- data/test/unit/search_size_from_test.rb +43 -0
- data/test/unit/search_sort_test.rb +40 -0
- data/test/unit/search_suggest_test.rb +20 -0
- data/test/unit/search_test.rb +201 -0
- data/test/unit/utils_test.rb +21 -0
- metadata +524 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8f022719f270cffd657795f61f6f90a4b6b5cece
|
4
|
+
data.tar.gz: 6ad90bcc1c4088c814290d11aa6ce8e30c1b7bed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33d9acad04bf367d192fbe1f75d69e56cdc2cf656e27889c5653f91e1ca24b9040d3d5afad0f5ef2638291c958a79dd659b9a48f5cb06ccc87c2b9f4143a014e
|
7
|
+
data.tar.gz: c4a2b3afc45f69f75ba6483484feac3340f8069f6149e6a69f506869e593f53b922b0fcb61837c74cb585bf5afcf15b540592e41d36418bc0a429695d807752e
|
data/Gemfile
CHANGED
@@ -2,3 +2,19 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in elasticsearch-dsl.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
if File.exists? File.expand_path("../../elasticsearch/elasticsearch.gemspec", __FILE__)
|
7
|
+
gem 'elasticsearch', :path => File.expand_path("../../elasticsearch", __FILE__), :require => false
|
8
|
+
end
|
9
|
+
|
10
|
+
if File.exists? File.expand_path("../../elasticsearch-transport", __FILE__)
|
11
|
+
gem 'elasticsearch-transport', :path => File.expand_path("../../elasticsearch-transport", __FILE__), :require => true
|
12
|
+
end
|
13
|
+
|
14
|
+
if File.exists? File.expand_path("../../elasticsearch-api", __FILE__)
|
15
|
+
gem 'elasticsearch-api', :path => File.expand_path("../../elasticsearch-api", __FILE__), :require => false
|
16
|
+
end
|
17
|
+
|
18
|
+
if File.exists? File.expand_path("../../elasticsearch-extensions", __FILE__)
|
19
|
+
gem 'elasticsearch-extensions', :path => File.expand_path("../../elasticsearch-extensions", __FILE__), :require => false
|
20
|
+
end
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,13 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2014 Elasticsearch
|
2
2
|
|
3
|
-
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
4
6
|
|
5
|
-
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -1,29 +1,258 @@
|
|
1
|
-
# Elasticsearch::
|
1
|
+
# Elasticsearch::DSL
|
2
2
|
|
3
|
-
|
3
|
+
The `elasticsearch-dsl` library provides a Ruby API for
|
4
|
+
the [Elasticsearch Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html).
|
5
|
+
|
6
|
+
The library is compatible with Ruby 1.9 or higher and Elasticsearch 1.0 and higher.
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
7
|
-
|
10
|
+
Install the package from [Rubygems](https://rubygems.org):
|
8
11
|
|
9
|
-
gem
|
12
|
+
gem install elasticsearch-dsl
|
10
13
|
|
11
|
-
|
14
|
+
To use an unreleased version, either add it to your `Gemfile` for [Bundler](http://gembundler.com):
|
12
15
|
|
13
|
-
|
16
|
+
gem 'elasticsearch-dsl', git: 'git://github.com/elasticsearch/elasticsearch-ruby.git'
|
14
17
|
|
15
|
-
|
18
|
+
or install it from a source code checkout:
|
16
19
|
|
17
|
-
|
20
|
+
git clone https://github.com/elasticsearch/elasticsearch-ruby.git
|
21
|
+
cd elasticsearch-ruby/elasticsearch-dsl
|
22
|
+
bundle install
|
23
|
+
rake install
|
18
24
|
|
19
25
|
## Usage
|
20
26
|
|
21
|
-
|
27
|
+
The library is designed as a group of standalone Ruby modules, classes and DSL methods,
|
28
|
+
which provide an idiomatic way to build complex
|
29
|
+
[search definitions](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html).
|
30
|
+
|
31
|
+
Let's have a simple example using the declarative variant:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'elasticsearch/dsl'
|
35
|
+
include Elasticsearch::DSL
|
36
|
+
|
37
|
+
definition = search do
|
38
|
+
query do
|
39
|
+
match title: 'test'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
definition.to_hash
|
44
|
+
# => { query: { match: { title: "test"} } }
|
45
|
+
|
46
|
+
require 'elasticsearch'
|
47
|
+
client = Elasticsearch::Client.new trace: true
|
48
|
+
|
49
|
+
client.search body: definition
|
50
|
+
# curl -X GET 'http://localhost:9200/test/_search?pretty' -d '{
|
51
|
+
# "query":{
|
52
|
+
# "match":{
|
53
|
+
# "title":"test"
|
54
|
+
# }
|
55
|
+
# }
|
56
|
+
# }'
|
57
|
+
# ...
|
58
|
+
# => {"took"=>10, "hits"=> {"total"=>42, "hits"=> [...] } }
|
59
|
+
```
|
60
|
+
|
61
|
+
Let's build the same definition in a more imperative fashion:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
require 'elasticsearch/dsl'
|
65
|
+
include Elasticsearch::DSL
|
66
|
+
|
67
|
+
definition = Search::Search.new
|
68
|
+
definition.query = Search::Queries::Match.new title: 'test'
|
69
|
+
|
70
|
+
definition.to_hash
|
71
|
+
# => { query: { match: { title: "test"} } }
|
72
|
+
```
|
73
|
+
|
74
|
+
The library doesn't depend on an Elasticsearch client -- its sole purpose is to facilitate
|
75
|
+
building search definitions in Ruby. This makes it possible to use it with any Elasticsearch client:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
require 'elasticsearch/dsl'
|
79
|
+
include Elasticsearch::DSL
|
80
|
+
|
81
|
+
definition = search { query { match title: 'test' } }
|
82
|
+
|
83
|
+
require 'json'
|
84
|
+
require 'faraday'
|
85
|
+
client = Faraday.new(url: 'http://localhost:9200')
|
86
|
+
response = JSON.parse(
|
87
|
+
client.post(
|
88
|
+
'/_search',
|
89
|
+
JSON.dump(definition.to_hash),
|
90
|
+
{ 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
|
91
|
+
).body
|
92
|
+
)
|
93
|
+
# => {"took"=>10, "hits"=> {"total"=>42, "hits"=> [...] } }
|
94
|
+
```
|
95
|
+
|
96
|
+
## Features Overview
|
97
|
+
|
98
|
+
The library allows to programatically build complex search definitions for Elasticsearch in Ruby,
|
99
|
+
which are translated to Hashes, and ultimately, JSON, the language of Elasticsearch.
|
100
|
+
|
101
|
+
All Elasticsearch DSL features are supported, namely:
|
102
|
+
|
103
|
+
* [Queries](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html)
|
104
|
+
* [Filters](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filters.html)
|
105
|
+
* [Aggregations](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html)
|
106
|
+
* [Suggestions](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html)
|
107
|
+
* [Sorting](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html)
|
108
|
+
* [Pagination](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html)
|
109
|
+
* [Options](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html) (source filtering, highlighting, etc)
|
110
|
+
|
111
|
+
An example of a complex search definition would look like this:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
require 'awesome_print'
|
115
|
+
|
116
|
+
require 'elasticsearch'
|
117
|
+
require 'elasticsearch/dsl'
|
118
|
+
|
119
|
+
include Elasticsearch::DSL
|
120
|
+
|
121
|
+
client = Elasticsearch::Client.new transport_options: { request: { timeout: 3600, open_timeout: 3600 } }
|
122
|
+
|
123
|
+
# Restore an index from a snapshot
|
124
|
+
#
|
125
|
+
client.indices.delete index: 'bicycles.stackexchange.com', ignore: 404
|
126
|
+
|
127
|
+
puts "Recovering the 'bicycles.stackexchange.com' index...".gray
|
128
|
+
client.snapshot.create_repository repository: 'data.elasticsearch.org', body: { type: 'url', settings: { url: 'https://s3.amazonaws.com/data.elasticsearch.org/bicycles.stackexchange.com/' } }
|
129
|
+
client.snapshot.restore repository: 'data.elasticsearch.org', snapshot: 'bicycles.stackexchange.com', body: { indices: 'bicycles.stackexchange.com' }
|
130
|
+
until client.cluster.health(level: 'indices')['indices']['bicycles.stackexchange.com']['status'] == 'green'
|
131
|
+
r = client.indices.status(index: 'bicycles.stackexchange.com', human: true, recovery: true)['indices']['bicycles.stackexchange.com']['shards']['0'][0]
|
132
|
+
print "\r#{r['index']['size']} of #{r['gateway_recovery']['index']['expected_recovered_size']}".ljust(52).gray
|
133
|
+
sleep 1
|
134
|
+
end
|
135
|
+
|
136
|
+
# The search definition
|
137
|
+
#
|
138
|
+
definition = search {
|
139
|
+
query do
|
140
|
+
|
141
|
+
# Use a `function_score` query to modify the default score
|
142
|
+
#
|
143
|
+
function_score do
|
144
|
+
query do
|
145
|
+
filtered do
|
146
|
+
|
147
|
+
# Use a `multi_match` query for the fulltext part of the search
|
148
|
+
#
|
149
|
+
query do
|
150
|
+
multi_match do
|
151
|
+
query 'fixed fixie'
|
152
|
+
operator 'or'
|
153
|
+
fields %w[ title^10 body ]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Use a `range` filter on the `creation_date` field
|
158
|
+
#
|
159
|
+
filter do
|
160
|
+
range :creation_date do
|
161
|
+
gte '2013-01-01'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Multiply the default `_score` by a (slightly normalized) document rating
|
168
|
+
#
|
169
|
+
functions << { script_score: { script: '_score * log10( doc["rating"].value )' } }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Calculate the most frequently used tags
|
174
|
+
#
|
175
|
+
aggregation :tags do
|
176
|
+
terms do
|
177
|
+
field 'tags'
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Calculate the posting frequency
|
182
|
+
#
|
183
|
+
aggregation :frequency do
|
184
|
+
date_histogram do
|
185
|
+
field 'creation_date'
|
186
|
+
interval 'month'
|
187
|
+
format 'yyyy-MM'
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Calculate the statistical information about the number of comments
|
192
|
+
#
|
193
|
+
aggregation :comment_count_stats do
|
194
|
+
stats field: 'comment_count'
|
195
|
+
end
|
196
|
+
|
197
|
+
# Highlight the `title` and `body` fields
|
198
|
+
#
|
199
|
+
highlight fields: {
|
200
|
+
title: { fragment_size: 50 },
|
201
|
+
body: { fragment_size: 50 }
|
202
|
+
}
|
203
|
+
|
204
|
+
# Return only a selection of the fields
|
205
|
+
#
|
206
|
+
source ['title', 'tags', 'creation_date', 'rating', 'user.location', 'user.display_name']
|
207
|
+
}
|
208
|
+
|
209
|
+
puts "Search definition #{'-'*63}\n".gray
|
210
|
+
ap definition.to_hash
|
211
|
+
|
212
|
+
# Execute the search request
|
213
|
+
#
|
214
|
+
response = client.search index: 'bicycles.stackexchange.com', type: ['question','answer'], body: definition
|
215
|
+
|
216
|
+
puts "\nSearch results #{'-'*66}\n".gray
|
217
|
+
ap response
|
218
|
+
```
|
219
|
+
|
220
|
+
**Please see the extensive RDoc examples in the source code and the integration tests.**
|
221
|
+
|
222
|
+
## Development
|
223
|
+
|
224
|
+
To work on the code, clone the repository and install the dependencies:
|
225
|
+
|
226
|
+
```
|
227
|
+
git clone https://github.com/elasticsearch/elasticsearch-ruby.git
|
228
|
+
cd elasticsearch-ruby/elasticsearch-dsl/
|
229
|
+
bundle install
|
230
|
+
```
|
231
|
+
|
232
|
+
Use the Rake tasks to run the test suites:
|
233
|
+
|
234
|
+
```
|
235
|
+
bundle exec rake test:unit
|
236
|
+
bundle exec rake test:integration
|
237
|
+
```
|
238
|
+
|
239
|
+
To launch a separate Elasticsearch server for integration tests,
|
240
|
+
see instructions in the main [README](../README.md#development).
|
241
|
+
|
242
|
+
## License
|
243
|
+
|
244
|
+
This software is licensed under the Apache 2 license, quoted below.
|
245
|
+
|
246
|
+
Copyright (c) 2015 Elasticsearch <http://www.elasticsearch.org>
|
247
|
+
|
248
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
249
|
+
you may not use this file except in compliance with the License.
|
250
|
+
You may obtain a copy of the License at
|
22
251
|
|
23
|
-
|
252
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
24
253
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
254
|
+
Unless required by applicable law or agreed to in writing, software
|
255
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
256
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
257
|
+
See the License for the specific language governing permissions and
|
258
|
+
limitations under the License.
|
data/Rakefile
CHANGED
@@ -1 +1,213 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
task(:default) { system "rake --tasks" }
|
4
|
+
task :test => 'test:unit'
|
5
|
+
|
6
|
+
# ----- Test tasks ------------------------------------------------------------
|
7
|
+
|
8
|
+
require 'rake/testtask'
|
9
|
+
namespace :test do
|
10
|
+
|
11
|
+
Rake::TestTask.new(:unit) do |test|
|
12
|
+
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
13
|
+
test.libs << 'lib' << 'test'
|
14
|
+
test.test_files = FileList["test/unit/**/*_test.rb"]
|
15
|
+
# test.verbose = true
|
16
|
+
# test.warning = true
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::TestTask.new(:integration) do |test|
|
20
|
+
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.test_files = FileList["test/integration/**/*_test.rb"]
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Run unit and integration tests"
|
26
|
+
task :all do
|
27
|
+
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
28
|
+
Rake::Task['test:unit'].invoke
|
29
|
+
Rake::Task['test:integration'].invoke
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :cluster do
|
33
|
+
desc "Start Elasticsearch nodes for tests"
|
34
|
+
task :start do
|
35
|
+
$LOAD_PATH << File.expand_path('../../elasticsearch-transport/lib', __FILE__) << File.expand_path('../test', __FILE__)
|
36
|
+
require 'elasticsearch/extensions/test/cluster'
|
37
|
+
Elasticsearch::Extensions::Test::Cluster.start
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Stop Elasticsearch nodes for tests"
|
41
|
+
task :stop do
|
42
|
+
$LOAD_PATH << File.expand_path('../../elasticsearch-transport/lib', __FILE__) << File.expand_path('../test', __FILE__)
|
43
|
+
require 'elasticsearch/extensions/test/cluster'
|
44
|
+
Elasticsearch::Extensions::Test::Cluster.stop
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# ----- Documentation tasks ---------------------------------------------------
|
50
|
+
|
51
|
+
require 'yard'
|
52
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
53
|
+
t.options = %w| --embed-mixins --markup=markdown |
|
54
|
+
end
|
55
|
+
|
56
|
+
# ----- Code analysis tasks ---------------------------------------------------
|
57
|
+
|
58
|
+
require 'cane/rake_task'
|
59
|
+
Cane::RakeTask.new(:quality) do |cane|
|
60
|
+
cane.abc_max = 15
|
61
|
+
cane.no_style = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# ----- Generating the source code --------------------------------------------
|
65
|
+
|
66
|
+
require 'net/http'
|
67
|
+
require 'json'
|
68
|
+
require 'coderay'
|
69
|
+
|
70
|
+
namespace :generate do
|
71
|
+
desc <<-DESC.gsub(/^ /, '')
|
72
|
+
Generate Ruby source and tests for query/filter/aggregation
|
73
|
+
|
74
|
+
Pass the type of the component, the name, and any option methods as Rake task arguments.
|
75
|
+
|
76
|
+
Example:
|
77
|
+
|
78
|
+
$ rake generate:source[query,boosting]
|
79
|
+
Source: /.../elasticsearch-ruby/elasticsearch-dsl/lib/elasticsearch/dsl/search/queries/boosting.rb
|
80
|
+
...
|
81
|
+
Test: /.../elasticsearch-ruby/elasticsearch-dsl/test/unit/queries/boosting_test.rb
|
82
|
+
...
|
83
|
+
|
84
|
+
$ rake generate:source[query,common,query/cutoff_frequency/low_freq_operator/...]
|
85
|
+
Source: /.../elasticsearch-ruby/elasticsearch-dsl/lib/elasticsearch/dsl/search/queries/common.rb
|
86
|
+
...
|
87
|
+
Test: /.../elasticsearch-ruby/elasticsearch-dsl/test/unit/queries/common_test.rb
|
88
|
+
...
|
89
|
+
|
90
|
+
DESC
|
91
|
+
task :source, [:type, :name, :option_methods] do |task, options|
|
92
|
+
begin
|
93
|
+
query = URI.escape("#{options[:name]} #{options[:type]}")
|
94
|
+
response = Net::HTTP.get('search.elasticsearch.org', "/search/?q=#{query}")
|
95
|
+
hits = JSON.load(response)['hits']['hits']
|
96
|
+
|
97
|
+
if hit = hits.first
|
98
|
+
doc_url = ("http://elasticsearch.org" + hit['fields']['url']).gsub(/#.+$/, '') if hit['_score'] > 0.2
|
99
|
+
end
|
100
|
+
rescue Exception => e
|
101
|
+
puts "[!] ERROR: #{e.inspect}"
|
102
|
+
end unless ENV['NOCRAWL']
|
103
|
+
|
104
|
+
case options[:type]
|
105
|
+
when /query/
|
106
|
+
module_name = 'Queries'
|
107
|
+
path_name = 'queries'
|
108
|
+
include_module = 'BaseComponent'
|
109
|
+
when /filter/
|
110
|
+
module_name = 'Filters'
|
111
|
+
path_name = 'filters'
|
112
|
+
include_module = 'BaseComponent'
|
113
|
+
when /agg/
|
114
|
+
module_name = 'Aggregations'
|
115
|
+
path_name = 'aggregations'
|
116
|
+
include_module = 'BaseAggregationComponent'
|
117
|
+
else raise ArgumentError, "Unknown DSL type [#{options[:type]}]"
|
118
|
+
end
|
119
|
+
|
120
|
+
name = options[:name].downcase
|
121
|
+
|
122
|
+
class_name = options[:name].split('_').map(&:capitalize).join
|
123
|
+
|
124
|
+
option_methods = options[:option_methods].to_s.split('/').reduce('') do |sum, item|
|
125
|
+
sum << " "
|
126
|
+
sum << "option_method :#{item}"
|
127
|
+
sum << "\n" unless item == options[:option_methods].to_s.split('/').last
|
128
|
+
sum
|
129
|
+
end
|
130
|
+
|
131
|
+
option_methods = "\n\n#{option_methods}" unless option_methods.empty?
|
132
|
+
|
133
|
+
source = <<-RUBY.gsub(/^ /, '')
|
134
|
+
module Elasticsearch
|
135
|
+
module DSL
|
136
|
+
module Search
|
137
|
+
module #{module_name}
|
138
|
+
|
139
|
+
# #{class_name} #{options[:type]}
|
140
|
+
#
|
141
|
+
# @example
|
142
|
+
#
|
143
|
+
# @see #{doc_url}
|
144
|
+
#
|
145
|
+
class #{class_name}
|
146
|
+
include #{include_module}#{option_methods}
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
RUBY
|
154
|
+
|
155
|
+
if options[:option_methods].to_s.empty?
|
156
|
+
test_option_methods = ''
|
157
|
+
else
|
158
|
+
setup = "\n" + options[:option_methods].to_s.split('/').reduce('') do |sum,item|
|
159
|
+
sum << " subject.#{item} 'bar'\n"; sum
|
160
|
+
end
|
161
|
+
asserts = "\n assert_equal %w[ #{options[:option_methods].to_s.split('/').sort.join(' ')} ],\n subject.to_hash[:#{name}][:foo].keys.map(&:to_s).sort"
|
162
|
+
asserts << "\n assert_equal 'bar', subject.to_hash[:#{name}][:foo][:#{options[:option_methods].to_s.split('/').first}]"
|
163
|
+
|
164
|
+
test_option_methods = <<-RUBY.gsub(/^ /, '')
|
165
|
+
|
166
|
+
should "have option methods" do
|
167
|
+
subject = #{class_name}.new :foo
|
168
|
+
#{setup}#{asserts}
|
169
|
+
end
|
170
|
+
|
171
|
+
should "take a block" do
|
172
|
+
subject = #{class_name}.new :foo do
|
173
|
+
#{options[:option_methods].to_s.split('/').first} 'bar'
|
174
|
+
end
|
175
|
+
assert_equal({#{name}: { foo: { #{options[:option_methods].to_s.split('/').first}: 'bar' } }}, subject.to_hash)
|
176
|
+
end
|
177
|
+
RUBY
|
178
|
+
end
|
179
|
+
|
180
|
+
test = <<-RUBY.gsub(/^ /, '')
|
181
|
+
require 'test_helper'
|
182
|
+
|
183
|
+
module Elasticsearch
|
184
|
+
module Test
|
185
|
+
module #{module_name}
|
186
|
+
class #{class_name}Test < ::Test::Unit::TestCase
|
187
|
+
include Elasticsearch::DSL::Search::#{module_name}
|
188
|
+
|
189
|
+
context "#{class_name} #{options[:type]}" do
|
190
|
+
subject { #{class_name}.new }
|
191
|
+
|
192
|
+
should "be converted to a Hash" do
|
193
|
+
assert_equal({ #{name}: {} }, subject.to_hash)
|
194
|
+
end
|
195
|
+
#{test_option_methods.empty? ? '' : test_option_methods.split("\n").map { |l| ' ' + l }.join("\n")}
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
RUBY
|
202
|
+
|
203
|
+
source_full_path = File.expand_path("../lib/elasticsearch/dsl/search/#{path_name}/#{name}.rb", __FILE__)
|
204
|
+
test_full_path = File.expand_path("../test/unit/#{path_name}/#{name}_test.rb", __FILE__)
|
205
|
+
|
206
|
+
puts '-'*80, "Source: #{source_full_path}", '-'*80, "\n", CodeRay.scan(source, :ruby).terminal, "\n\n"
|
207
|
+
puts '-'*80, "Test: #{test_full_path}", '-'*80, "\n", CodeRay.scan(test, :ruby).terminal, "\n"
|
208
|
+
|
209
|
+
File.open(source_full_path, 'w') { |file| file << source }
|
210
|
+
|
211
|
+
File.open(test_full_path, 'w') { |file| file << test }
|
212
|
+
end
|
213
|
+
end
|