rom-elasticsearch 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.travis.yml +24 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +20 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +19 -0
- data/lib/rom-elasticsearch.rb +1 -0
- data/lib/rom/elasticsearch.rb +8 -0
- data/lib/rom/elasticsearch/attribute.rb +30 -0
- data/lib/rom/elasticsearch/commands.rb +49 -0
- data/lib/rom/elasticsearch/dataset.rb +219 -0
- data/lib/rom/elasticsearch/errors.rb +23 -0
- data/lib/rom/elasticsearch/gateway.rb +81 -0
- data/lib/rom/elasticsearch/plugins/relation/query_dsl.rb +57 -0
- data/lib/rom/elasticsearch/query_methods.rb +64 -0
- data/lib/rom/elasticsearch/relation.rb +241 -0
- data/lib/rom/elasticsearch/schema.rb +26 -0
- data/lib/rom/elasticsearch/types.rb +33 -0
- data/lib/rom/elasticsearch/version.rb +5 -0
- data/rom-elasticsearch.gemspec +27 -0
- data/spec/integration/rom/elasticsearch/relation/command_spec.rb +47 -0
- data/spec/shared/setup.rb +16 -0
- data/spec/shared/unit/user_fixtures.rb +15 -0
- data/spec/shared/unit/users.rb +18 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/unit/rom/elasticsearch/dataset/body_spec.rb +13 -0
- data/spec/unit/rom/elasticsearch/dataset/delete_spec.rb +17 -0
- data/spec/unit/rom/elasticsearch/dataset/params_spec.rb +13 -0
- data/spec/unit/rom/elasticsearch/dataset/put_spec.rb +14 -0
- data/spec/unit/rom/elasticsearch/dataset/query_string_spec.rb +12 -0
- data/spec/unit/rom/elasticsearch/dataset/search_spec.rb +20 -0
- data/spec/unit/rom/elasticsearch/gateway_spec.rb +10 -0
- data/spec/unit/rom/elasticsearch/plugins/relation/query_dsl_spec.rb +34 -0
- data/spec/unit/rom/elasticsearch/relation/create_index_spec.rb +75 -0
- data/spec/unit/rom/elasticsearch/relation/dataset_spec.rb +26 -0
- data/spec/unit/rom/elasticsearch/relation/delete_spec.rb +32 -0
- data/spec/unit/rom/elasticsearch/relation/get_spec.rb +22 -0
- data/spec/unit/rom/elasticsearch/relation/map_spec.rb +18 -0
- data/spec/unit/rom/elasticsearch/relation/pluck_spec.rb +18 -0
- data/spec/unit/rom/elasticsearch/relation/query_spec.rb +18 -0
- data/spec/unit/rom/elasticsearch/relation/query_string_spec.rb +18 -0
- data/spec/unit/rom/elasticsearch/relation/search_spec.rb +18 -0
- data/spec/unit/rom/elasticsearch/relation/to_a_spec.rb +28 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7ea7ae9dbc43c75ca9583e5df195db789ea28430
|
4
|
+
data.tar.gz: 2d1b2523c9acc5c248b1841685588c73943e8990
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 887ffb629635a427b714a6e66cc8f4ba54251efa5b17ec8c70d1f8704f9b79de460b30402c437b38bb0da75b09d860e1ae5048f6feda933d5560b029f85fae9d
|
7
|
+
data.tar.gz: 46b872af00f24af35f1ea18cfbcda7dc5d2b2fedbdeea110c08c142c7199424d80218a7deab7c65e3fdfab90271320a2e6fa25eaf9e219856465a8f76ec9bc60
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache: bundler
|
4
|
+
services:
|
5
|
+
- elasticsearch
|
6
|
+
bundler_args: --without yard guard benchmarks tools
|
7
|
+
before_script:
|
8
|
+
- curl -XPUT http://localhost:9200/rom-test
|
9
|
+
script: "bundle exec rake ci"
|
10
|
+
rvm:
|
11
|
+
- 2.3.4
|
12
|
+
- 2.4.1
|
13
|
+
- jruby-9.1.12.0
|
14
|
+
env:
|
15
|
+
global:
|
16
|
+
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
17
|
+
- COVERAGE='true'
|
18
|
+
notifications:
|
19
|
+
webhooks:
|
20
|
+
urls:
|
21
|
+
- https://webhooks.gitter.im/e/39e1225f489f38b0bd09
|
22
|
+
on_success: change
|
23
|
+
on_failure: always
|
24
|
+
on_start: false
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Issue Guidelines
|
2
|
+
|
3
|
+
## Reporting bugs
|
4
|
+
|
5
|
+
If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
|
6
|
+
|
7
|
+
## Reporting feature requests
|
8
|
+
|
9
|
+
Report a feature request **only after discussing it first on [discourse.rom-rb.org](https://discourse.rom-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discussion thread, and instead summarize what was discussed.
|
10
|
+
|
11
|
+
## Reporting questions, support requests, ideas, concerns etc.
|
12
|
+
|
13
|
+
**PLEASE DON'T** - use [discourse.rom-rb.org](http://discourse.rom-rb.org) instead.
|
14
|
+
|
15
|
+
# Pull Request Guidelines
|
16
|
+
|
17
|
+
A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
|
18
|
+
|
19
|
+
Other requirements:
|
20
|
+
|
21
|
+
1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
|
22
|
+
2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
|
23
|
+
3) Add API documentation if it's a new feature
|
24
|
+
4) Update API documentation if it changes an existing feature
|
25
|
+
5) Bonus points for sending a PR to [github.com/rom-rb/rom-rb.org](https://github.com/rom-rb/rom-rb.org) which updates user documentation and guides
|
26
|
+
|
27
|
+
# Asking for help
|
28
|
+
|
29
|
+
If these guidelines aren't helpful, and you're stuck, please post a message on [discourse.rom-rb.org](https://discourse.rom-rb.org).
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in rom-elasticsearch.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'rom', git: 'https://github.com/rom-rb/rom', branch: 'master' do
|
7
|
+
gem 'rom-core'
|
8
|
+
gem 'rom-mapper'
|
9
|
+
end
|
10
|
+
|
11
|
+
gem 'codeclimate-test-reporter', require: false
|
12
|
+
gem 'simplecov', require: false
|
13
|
+
|
14
|
+
gem 'pry-byebug', platform: :mri
|
15
|
+
gem 'pry', platform: :jruby
|
16
|
+
gem 'elasticsearch-dsl'
|
17
|
+
|
18
|
+
group :tools do
|
19
|
+
gem 'kramdown' # for yard
|
20
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) rom-rb team
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
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:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
[gem]: https://rubygems.org/gems/rom-elasticsearch
|
2
|
+
[travis]: https://travis-ci.org/rom-rb/rom-elasticsearch
|
3
|
+
[gemnasium]: https://gemnasium.com/rom-rb/rom-elasticsearch
|
4
|
+
[codeclimate]: https://codeclimate.com/github/rom-rb/rom-elasticsearch
|
5
|
+
[inchpages]: http://inch-ci.org/github/rom-rb/rom-elasticsearch
|
6
|
+
|
7
|
+
# rom-elasticsearch
|
8
|
+
|
9
|
+
[][gem]
|
10
|
+
[][travis]
|
11
|
+
[][gemnasium]
|
12
|
+
[][codeclimate]
|
13
|
+
[][codeclimate]
|
14
|
+
[][inchpages]
|
15
|
+
|
16
|
+
ElasticSearch support for [rom-rb](https://github.com/rom-rb/rom).
|
17
|
+
|
18
|
+
Resources:
|
19
|
+
|
20
|
+
- [API Documentation](http://api.rom-rb.org/rom-elasticsearch)
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem 'rom-elasticsearch'
|
28
|
+
```
|
29
|
+
|
30
|
+
And then execute:
|
31
|
+
|
32
|
+
$ bundle
|
33
|
+
|
34
|
+
Or install it yourself as:
|
35
|
+
|
36
|
+
$ gem install rom-elasticsearch
|
37
|
+
|
38
|
+
## License
|
39
|
+
|
40
|
+
See `LICENSE` file.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
task default: [:ci]
|
6
|
+
|
7
|
+
desc "Run CI tasks"
|
8
|
+
task ci: [:spec]
|
9
|
+
|
10
|
+
begin
|
11
|
+
require "rubocop/rake_task"
|
12
|
+
|
13
|
+
Rake::Task[:default].enhance [:rubocop]
|
14
|
+
|
15
|
+
RuboCop::RakeTask.new do |task|
|
16
|
+
task.options << "--display-cop-names"
|
17
|
+
end
|
18
|
+
rescue LoadError
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rom/elasticsearch'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rom/attribute'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module Elasticsearch
|
5
|
+
# ES-specific attribute types for schemas
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
class Attribute < ROM::Attribute
|
9
|
+
INTERNAL_META_KEYS = %i[name source primary_key].freeze
|
10
|
+
|
11
|
+
# Return ES mapping properties
|
12
|
+
#
|
13
|
+
# @return [Hash]
|
14
|
+
#
|
15
|
+
# @api public
|
16
|
+
memoize def properties
|
17
|
+
type.meta.reject { |k, _| INTERNAL_META_KEYS.include?(k) }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return if an attribute has any ES mappings
|
21
|
+
#
|
22
|
+
# @return [Bool]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def properties?
|
26
|
+
properties.size > 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rom/commands'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module Elasticsearch
|
5
|
+
# ElasticSearch relation commands
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
class Commands
|
9
|
+
# Create command
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
class Create < ROM::Commands::Create
|
13
|
+
# @api private
|
14
|
+
def execute(attributes)
|
15
|
+
tuple = input[attributes]
|
16
|
+
|
17
|
+
result =
|
18
|
+
if _id
|
19
|
+
dataset.params(id: tuple.fetch(_id)).put(tuple)
|
20
|
+
else
|
21
|
+
dataset.put(tuple)
|
22
|
+
end
|
23
|
+
[relation.get(result['_id']).one]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def dataset
|
30
|
+
relation.dataset
|
31
|
+
end
|
32
|
+
|
33
|
+
def _id
|
34
|
+
relation.schema.primary_key_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Delete command
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
class Delete < ROM::Commands::Delete
|
42
|
+
# @api private
|
43
|
+
def execute
|
44
|
+
relation.dataset.delete
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require 'rom/initializer'
|
2
|
+
|
3
|
+
require 'rom/elasticsearch/query_methods'
|
4
|
+
require 'rom/elasticsearch/errors'
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
module Elasticsearch
|
8
|
+
# Elasticsearch dataset
|
9
|
+
#
|
10
|
+
# Uses an elasticsearch client object provided by the gateway, holds basic
|
11
|
+
# params with information about index name and type, and optional body for
|
12
|
+
# additional queries.
|
13
|
+
#
|
14
|
+
# Dataset object also provide meta information about indices, like custom
|
15
|
+
# settings and mappings.
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
class Dataset
|
19
|
+
extend Initializer
|
20
|
+
|
21
|
+
include QueryMethods
|
22
|
+
|
23
|
+
# Default query options
|
24
|
+
ALL = { query: { match_all: EMPTY_HASH } }.freeze
|
25
|
+
|
26
|
+
# The source key in raw results
|
27
|
+
SOURCE_KEY = '_source'.freeze
|
28
|
+
|
29
|
+
# @!attribute [r] client
|
30
|
+
# @return [::Elasticsearch::Client] configured client from the gateway
|
31
|
+
param :client
|
32
|
+
|
33
|
+
# @!attribute [r] params
|
34
|
+
# @return [Hash] default params
|
35
|
+
option :params, default: -> { EMPTY_HASH }
|
36
|
+
|
37
|
+
# @!attribute [r] client
|
38
|
+
# @return [Hash] default body
|
39
|
+
option :body, default: -> { EMPTY_HASH }
|
40
|
+
|
41
|
+
# Put new data under configured index
|
42
|
+
#
|
43
|
+
# @param [Hash] data
|
44
|
+
#
|
45
|
+
# @return [Hash]
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def put(data)
|
49
|
+
client.index(**params, body: data)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return index settings
|
53
|
+
#
|
54
|
+
# @return [Hash]
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def settings
|
58
|
+
client.indices.get_settings[index.to_s]['settings']['index']
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return index mappings
|
62
|
+
#
|
63
|
+
# @return [Hash]
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def mappings
|
67
|
+
client.indices.get_mapping[index.to_s]['mappings'][type.to_s]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Delete everything matching configured params and/or body
|
71
|
+
#
|
72
|
+
# If body is empty it *will delete everything**
|
73
|
+
#
|
74
|
+
# @return [Hash] raw response hash from the client
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
def delete
|
78
|
+
if body.empty? && params[:id]
|
79
|
+
client.delete(params)
|
80
|
+
elsif body.empty?
|
81
|
+
client.delete_by_query(params.merge(body: body.merge(ALL)))
|
82
|
+
else
|
83
|
+
client.delete_by_query(params.merge(body: body))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Materialize the dataset
|
88
|
+
#
|
89
|
+
# @return [Array<Hash>]
|
90
|
+
#
|
91
|
+
# @api public
|
92
|
+
def to_a
|
93
|
+
to_enum.to_a
|
94
|
+
end
|
95
|
+
|
96
|
+
# Materialize and iterate over results
|
97
|
+
#
|
98
|
+
# @yieldparam [Hash]
|
99
|
+
#
|
100
|
+
# @raise [SearchError] in case of the client raising an exception
|
101
|
+
#
|
102
|
+
# @api public
|
103
|
+
def each
|
104
|
+
return to_enum unless block_given?
|
105
|
+
view.each do |result|
|
106
|
+
yield(result[SOURCE_KEY])
|
107
|
+
end
|
108
|
+
rescue ::Elasticsearch::Transport::Transport::Error => e
|
109
|
+
raise SearchError.new(e, options)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Map dataset tuples
|
113
|
+
#
|
114
|
+
# @yieldparam [Hash]
|
115
|
+
#
|
116
|
+
# @return [Array]
|
117
|
+
#
|
118
|
+
# @api public
|
119
|
+
def map(&block)
|
120
|
+
to_a.map(&block)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return configured type from params
|
124
|
+
#
|
125
|
+
# @return [Symbol]
|
126
|
+
#
|
127
|
+
# @api public
|
128
|
+
def type
|
129
|
+
params[:type]
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return configured index name
|
133
|
+
#
|
134
|
+
# @return [Symbol]
|
135
|
+
#
|
136
|
+
# @api public
|
137
|
+
def index
|
138
|
+
params[:index]
|
139
|
+
end
|
140
|
+
|
141
|
+
# Return a new dataset with new body
|
142
|
+
#
|
143
|
+
# @param [Hash] new New body data
|
144
|
+
#
|
145
|
+
# @return [Hash]
|
146
|
+
#
|
147
|
+
# @api public
|
148
|
+
def body(new = nil)
|
149
|
+
if new.nil?
|
150
|
+
@body
|
151
|
+
else
|
152
|
+
with(body: body.merge(new))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Return a new dataset with new params
|
157
|
+
#
|
158
|
+
# @param [Hash] new New params data
|
159
|
+
#
|
160
|
+
# @return [Hash]
|
161
|
+
#
|
162
|
+
# @api public
|
163
|
+
def params(new = nil)
|
164
|
+
if new.nil?
|
165
|
+
@params
|
166
|
+
else
|
167
|
+
with(params: params.merge(new))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Refresh index
|
172
|
+
#
|
173
|
+
# @return [Dataset]
|
174
|
+
#
|
175
|
+
# @api public
|
176
|
+
def refresh
|
177
|
+
client.indices.refresh(index: index)
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
# Create an index
|
182
|
+
#
|
183
|
+
# @param [Hash] opts ES options
|
184
|
+
#
|
185
|
+
# @api public
|
186
|
+
#
|
187
|
+
# @return [Hash]
|
188
|
+
def create_index(opts = EMPTY_HASH)
|
189
|
+
client.indices.create(params.merge(opts))
|
190
|
+
end
|
191
|
+
|
192
|
+
# Delete an index
|
193
|
+
#
|
194
|
+
# @param [Hash] opts ES options
|
195
|
+
#
|
196
|
+
# @api public
|
197
|
+
#
|
198
|
+
# @return [Hash]
|
199
|
+
def delete_index(opts = EMPTY_HASH)
|
200
|
+
client.indices.delete(params.merge(opts))
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
# Return results of a query based on configured params and body
|
206
|
+
#
|
207
|
+
# @return [Array<Hash>]
|
208
|
+
#
|
209
|
+
# @api private
|
210
|
+
def view
|
211
|
+
if params[:id]
|
212
|
+
[client.get(params)]
|
213
|
+
else
|
214
|
+
client.search(**params, body: body).fetch('hits').fetch('hits')
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|