elasticsearch-persistence 5.1.0 → 6.0.0.pre
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 +4 -4
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/README.md +164 -323
- data/Rakefile +8 -8
- data/elasticsearch-persistence.gemspec +4 -5
- data/lib/elasticsearch/persistence.rb +2 -110
- data/lib/elasticsearch/persistence/repository.rb +212 -53
- data/lib/elasticsearch/persistence/repository/dsl.rb +94 -0
- data/lib/elasticsearch/persistence/repository/find.rb +27 -10
- data/lib/elasticsearch/persistence/repository/response/results.rb +17 -5
- data/lib/elasticsearch/persistence/repository/search.rb +15 -4
- data/lib/elasticsearch/persistence/repository/serialize.rb +65 -7
- data/lib/elasticsearch/persistence/repository/store.rb +38 -44
- data/lib/elasticsearch/persistence/version.rb +1 -1
- data/spec/repository/find_spec.rb +179 -0
- data/spec/repository/response/results_spec.rb +105 -0
- data/spec/repository/search_spec.rb +181 -0
- data/spec/repository/serialize_spec.rb +53 -0
- data/spec/repository/store_spec.rb +327 -0
- data/spec/repository_spec.rb +716 -0
- data/spec/spec_helper.rb +28 -0
- metadata +25 -80
- data/lib/elasticsearch/persistence/client.rb +0 -51
- data/lib/elasticsearch/persistence/model.rb +0 -153
- data/lib/elasticsearch/persistence/model/base.rb +0 -87
- data/lib/elasticsearch/persistence/model/errors.rb +0 -8
- data/lib/elasticsearch/persistence/model/find.rb +0 -180
- data/lib/elasticsearch/persistence/model/rails.rb +0 -47
- data/lib/elasticsearch/persistence/model/store.rb +0 -254
- data/lib/elasticsearch/persistence/model/utils.rb +0 -0
- data/lib/elasticsearch/persistence/repository/class.rb +0 -71
- data/lib/elasticsearch/persistence/repository/naming.rb +0 -115
- data/lib/rails/generators/elasticsearch/model/model_generator.rb +0 -21
- data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +0 -9
- data/lib/rails/generators/elasticsearch_generator.rb +0 -2
- data/test/integration/model/model_basic_test.rb +0 -238
- data/test/integration/repository/custom_class_test.rb +0 -85
- data/test/integration/repository/customized_class_test.rb +0 -82
- data/test/integration/repository/default_class_test.rb +0 -116
- data/test/integration/repository/virtus_model_test.rb +0 -118
- data/test/test_helper.rb +0 -55
- data/test/unit/model_base_test.rb +0 -72
- data/test/unit/model_find_test.rb +0 -153
- data/test/unit/model_gateway_test.rb +0 -101
- data/test/unit/model_rails_test.rb +0 -112
- data/test/unit/model_store_test.rb +0 -576
- data/test/unit/persistence_test.rb +0 -32
- data/test/unit/repository_class_test.rb +0 -51
- data/test/unit/repository_client_test.rb +0 -32
- data/test/unit/repository_find_test.rb +0 -388
- data/test/unit/repository_indexing_test.rb +0 -37
- data/test/unit/repository_module_test.rb +0 -146
- data/test/unit/repository_naming_test.rb +0 -146
- data/test/unit/repository_response_results_test.rb +0 -98
- data/test/unit/repository_search_test.rb +0 -117
- data/test/unit/repository_serialize_test.rb +0 -57
- data/test/unit/repository_store_test.rb +0 -303
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elasticsearch::Persistence::Repository::Find do
|
4
|
+
|
5
|
+
after do
|
6
|
+
begin; repository.delete_index!; rescue; end
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:repository) do
|
10
|
+
DEFAULT_REPOSITORY
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#exists?' do
|
14
|
+
|
15
|
+
context 'when the document exists' do
|
16
|
+
|
17
|
+
let(:id) do
|
18
|
+
repository.save(a: 1)['_id']
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns true' do
|
22
|
+
expect(repository.exists?(id)).to be(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when the document does not exist' do
|
27
|
+
|
28
|
+
it 'returns false' do
|
29
|
+
expect(repository.exists?('1')).to be(false)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when options are provided' do
|
34
|
+
|
35
|
+
let(:id) do
|
36
|
+
repository.save(a: 1)['_id']
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'applies the options' do
|
40
|
+
expect(repository.exists?(id, type: 'other_type')).to be(false)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#find' do
|
46
|
+
|
47
|
+
context 'when options are not provided' do
|
48
|
+
|
49
|
+
context 'when a single id is provided' do
|
50
|
+
|
51
|
+
let!(:id) do
|
52
|
+
repository.save(a: 1)['_id']
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'retrieves the document' do
|
56
|
+
expect(repository.find(id)).to eq('a' => 1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when an array of ids is provided' do
|
61
|
+
|
62
|
+
let!(:ids) do
|
63
|
+
3.times.collect do |i|
|
64
|
+
repository.save(a: i)['_id']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'retrieves the documents' do
|
69
|
+
expect(repository.find(ids)).to eq([{ 'a' =>0 },
|
70
|
+
{ 'a' => 1 },
|
71
|
+
{ 'a' => 2 }])
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when some documents are found and some are not' do
|
75
|
+
|
76
|
+
before do
|
77
|
+
ids[1] = 22
|
78
|
+
ids
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns nil in the result list for the documents not found' do
|
82
|
+
expect(repository.find(ids)).to eq([{ 'a' =>0 },
|
83
|
+
nil,
|
84
|
+
{ 'a' => 2 }])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when multiple ids are provided' do
|
90
|
+
|
91
|
+
let!(:ids) do
|
92
|
+
3.times.collect do |i|
|
93
|
+
repository.save(a: i)['_id']
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'retrieves the documents' do
|
98
|
+
expect(repository.find(*ids)).to eq([{ 'a' =>0 },
|
99
|
+
{ 'a' => 1 },
|
100
|
+
{ 'a' => 2 }])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when the document cannot be found' do
|
105
|
+
|
106
|
+
before do
|
107
|
+
begin; repository.create_index!; rescue; end
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'raises a DocumentNotFound exception' do
|
111
|
+
expect {
|
112
|
+
repository.find(1)
|
113
|
+
}.to raise_exception(Elasticsearch::Persistence::Repository::DocumentNotFound)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'when options are provided' do
|
119
|
+
|
120
|
+
context 'when a single id is passed' do
|
121
|
+
|
122
|
+
let!(:id) do
|
123
|
+
repository.save(a: 1)['_id']
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'applies the options' do
|
127
|
+
expect {
|
128
|
+
repository.find(id, type: 'none')
|
129
|
+
}.to raise_exception(Elasticsearch::Persistence::Repository::DocumentNotFound)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'when an array of ids is passed' do
|
134
|
+
|
135
|
+
let!(:ids) do
|
136
|
+
3.times.collect do |i|
|
137
|
+
repository.save(a: i)['_id']
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'applies the options' do
|
142
|
+
expect(repository.find(ids, type: 'none')).to eq([nil, nil, nil])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'when multiple ids are passed' do
|
147
|
+
|
148
|
+
let!(:ids) do
|
149
|
+
3.times.collect do |i|
|
150
|
+
repository.save(a: i)['_id']
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'applies the options' do
|
155
|
+
expect(repository.find(*ids, type: 'none')).to eq([nil, nil, nil])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when a document_type is defined on the class' do
|
161
|
+
|
162
|
+
let(:repository) do
|
163
|
+
MyTestRepository.new(document_type:'other_type', client: DEFAULT_CLIENT, index_name: 'test')
|
164
|
+
end
|
165
|
+
|
166
|
+
let!(:ids) do
|
167
|
+
3.times.collect do |i|
|
168
|
+
repository.save(a: i)['_id']
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'uses the document type in the query' do
|
173
|
+
expect(repository.find(ids)).to eq([{ 'a' =>0 },
|
174
|
+
{ 'a' => 1 },
|
175
|
+
{ 'a' => 2 }])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elasticsearch::Persistence::Repository::Response::Results do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class MyRepository
|
7
|
+
include Elasticsearch::Persistence::Repository
|
8
|
+
|
9
|
+
def deserialize(document)
|
10
|
+
'Object'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:repository) do
|
16
|
+
MyRepository.new
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:all) do
|
20
|
+
if defined?(MyRepository)
|
21
|
+
Object.send(:remove_const, MyRepository.name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:response) do
|
26
|
+
{ "took" => 2,
|
27
|
+
"timed_out" => false,
|
28
|
+
"_shards" => {"total" => 5, "successful" => 5, "failed" => 0},
|
29
|
+
"hits" =>
|
30
|
+
{ "total" => 2,
|
31
|
+
"max_score" => 0.19,
|
32
|
+
"hits" =>
|
33
|
+
[{"_index" => "my_index",
|
34
|
+
"_type" => "note",
|
35
|
+
"_id" => "1",
|
36
|
+
"_score" => 0.19,
|
37
|
+
"_source" => {"id" => 1, "title" => "Test 1"}},
|
38
|
+
|
39
|
+
{"_index" => "my_index",
|
40
|
+
"_type" => "note",
|
41
|
+
"_id" => "2",
|
42
|
+
"_score" => 0.19,
|
43
|
+
"_source" => {"id" => 2, "title" => "Test 2"}}
|
44
|
+
]
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
let(:results) do
|
50
|
+
described_class.new(repository, response)
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#repository' do
|
54
|
+
|
55
|
+
it 'should return the repository' do
|
56
|
+
expect(results.repository).to be(repository)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#response' do
|
61
|
+
|
62
|
+
it 'returns the response' do
|
63
|
+
expect(results.response).to eq(response)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'wraps the response in a HashWrapper' do
|
67
|
+
expect(results.response._shards.total).to eq(5)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#total' do
|
72
|
+
|
73
|
+
it 'returns the total' do
|
74
|
+
expect(results.total).to eq(2)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#max_score' do
|
79
|
+
|
80
|
+
it 'returns the max score' do
|
81
|
+
expect(results.max_score).to eq(0.19)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#each' do
|
86
|
+
|
87
|
+
it 'delegates the method to the results' do
|
88
|
+
expect(results.size).to eq(2)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#each_with_hit' do
|
93
|
+
|
94
|
+
it 'returns each deserialized object with the raw document' do
|
95
|
+
expect(results.each_with_hit { |pair| pair[0] = 'Obj'}).to eq(['Obj', 'Obj'].zip(response['hits']['hits']))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#map_with_hit' do
|
100
|
+
|
101
|
+
it 'returns the result of the block called on a pair of each raw document and the deserialized object' do
|
102
|
+
expect(results.map_with_hit { |pair| pair[0] }).to eq(['Object', 'Object'])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elasticsearch::Persistence::Repository::Search do
|
4
|
+
|
5
|
+
after do
|
6
|
+
begin; repository.delete_index!; rescue; end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#search' do
|
10
|
+
|
11
|
+
let(:repository) do
|
12
|
+
DEFAULT_REPOSITORY
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when the repository does not have a type set' do
|
16
|
+
|
17
|
+
before do
|
18
|
+
repository.save({ name: 'user' }, refresh: true)
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when a query definition is provided as a hash' do
|
22
|
+
|
23
|
+
it 'uses the default document type' do
|
24
|
+
expect(repository.search({ query: { match: { name: 'user' } } }).first).to eq('name' => 'user')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when a query definition is provided as a string' do
|
29
|
+
|
30
|
+
it 'uses the default document type' do
|
31
|
+
expect(repository.search('user').first).to eq('name' => 'user')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when the query definition is neither a String nor a Hash' do
|
36
|
+
|
37
|
+
it 'raises an ArgumentError' do
|
38
|
+
expect {
|
39
|
+
repository.search(1)
|
40
|
+
}.to raise_exception(ArgumentError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when options are provided' do
|
45
|
+
|
46
|
+
context 'when a query definition is provided as a hash' do
|
47
|
+
|
48
|
+
it 'uses the default document type' do
|
49
|
+
expect(repository.search({ query: { match: { name: 'user' } } }, type: 'other').first).to be_nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when a query definition is provided as a string' do
|
54
|
+
|
55
|
+
it 'uses the default document type' do
|
56
|
+
expect(repository.search('user', type: 'other').first).to be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when the query definition is neither a String nor a Hash' do
|
61
|
+
|
62
|
+
it 'raises an ArgumentError' do
|
63
|
+
expect {
|
64
|
+
repository.search(1)
|
65
|
+
}.to raise_exception(ArgumentError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when the repository does have a type set' do
|
72
|
+
|
73
|
+
let(:repository) do
|
74
|
+
MyTestRepository.new(document_type: 'other_note')
|
75
|
+
end
|
76
|
+
|
77
|
+
before do
|
78
|
+
repository.save({ name: 'user' }, refresh: true)
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when options are provided' do
|
82
|
+
|
83
|
+
context 'when a query definition is provided as a hash' do
|
84
|
+
|
85
|
+
it 'uses the options' do
|
86
|
+
expect(repository.search({ query: { match: { name: 'user' } } }, type: 'other').first).to be_nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when a query definition is provided as a string' do
|
91
|
+
|
92
|
+
it 'uses the options' do
|
93
|
+
expect(repository.search('user', type: 'other').first).to be_nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when the query definition is neither a String nor a Hash' do
|
98
|
+
|
99
|
+
it 'raises an ArgumentError' do
|
100
|
+
expect {
|
101
|
+
repository.search(1)
|
102
|
+
}.to raise_exception(ArgumentError)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#count' do
|
110
|
+
|
111
|
+
context 'when the repository does not have a type set' do
|
112
|
+
|
113
|
+
let(:repository) do
|
114
|
+
DEFAULT_REPOSITORY
|
115
|
+
end
|
116
|
+
|
117
|
+
before do
|
118
|
+
repository.save({ name: 'user' }, refresh: true)
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when a query definition is provided as a hash' do
|
122
|
+
|
123
|
+
it 'uses the default document type' do
|
124
|
+
expect(repository.count({ query: { match: { name: 'user' } } })).to eq(1)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when a query definition is provided as a string' do
|
129
|
+
|
130
|
+
it 'uses the default document type' do
|
131
|
+
expect(repository.count('user')).to eq(1)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when options are provided' do
|
136
|
+
|
137
|
+
context 'when a query definition is provided as a hash' do
|
138
|
+
|
139
|
+
it 'uses the options' do
|
140
|
+
expect(repository.count({ query: { match: { name: 'user' } } }, type: 'other')).to eq(0)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'when a query definition is provided as a string' do
|
145
|
+
|
146
|
+
it 'uses the options' do
|
147
|
+
expect(repository.count('user', type: 'other')).to eq(0)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'when the repository does have a type set' do
|
154
|
+
|
155
|
+
let(:repository) do
|
156
|
+
MyTestRepository.new(document_type: 'other_note')
|
157
|
+
end
|
158
|
+
|
159
|
+
before do
|
160
|
+
repository.save({ name: 'user' }, refresh: true)
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when options are provided' do
|
164
|
+
|
165
|
+
context 'when a query definition is provided as a hash' do
|
166
|
+
|
167
|
+
it 'uses the options' do
|
168
|
+
expect(repository.count({ query: { match: { name: 'user' } } }, type: 'other')).to eq(0)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'when a query definition is provided as a string' do
|
173
|
+
|
174
|
+
it 'uses the options' do
|
175
|
+
expect(repository.count('user', type: 'other')).to eq(0)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|