cloudsearchable 0.0.3 → 1.0.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/.rspec +1 -0
- data/LICENSE.txt +10 -18
- data/README.md +8 -6
- data/Rakefile +1 -1
- data/cloudsearchable.gemspec +2 -2
- data/lib/cloudsearchable/cloud_search.rb +2 -3
- data/lib/cloudsearchable/version.rb +1 -1
- data/spec/cloudsearchable/cloud_search_spec.rb +5 -4
- data/spec/cloudsearchable/cloudsearchable_spec.rb +14 -14
- data/spec/cloudsearchable/config/option_spec.rb +6 -6
- data/spec/cloudsearchable/config_spec.rb +2 -2
- data/spec/cloudsearchable/domain_spec.rb +18 -18
- data/spec/cloudsearchable/field_spec.rb +10 -6
- data/spec/cloudsearchable/query_chain_spec.rb +47 -47
- data/spec/spec_helper.rb +1 -0
- data/spec/test_classes/cloud_searchable_test_class.rb +4 -4
- metadata +24 -39
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 977311a4dc8f21c3619d10a0cf09641d115daaca
|
4
|
+
data.tar.gz: 10e9103f7e75c26adb34311c63ceda1048290ce6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4e78c50baf6fbd8b31a84f96d513b922287481d23b5c3c724ce65405e9790dec7b7f643c04edc4477499a1cee73063d99da94fffa0ee360338769842da550ef4
|
7
|
+
data.tar.gz: 791a74806038012011dc9590628c5695d9519d8ea89e2713707ac67bc4f6e147ded776feb58c77cedc49e5db7bca17ee10c44a7400d170193b985b9c5522ccf3
|
data/.rspec
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,22 +1,14 @@
|
|
1
|
-
Copyright (c) 2013
|
1
|
+
Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
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
|
-
|
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.
|
15
14
|
|
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
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Cloudsearchable
|
2
|
-
An ActiveRecord-style ORM query interface for
|
2
|
+
An ActiveRecord-style ORM query interface for [Amazon CloudSearch](https://aws.amazon.com/cloudsearch/).
|
3
|
+
|
4
|
+
[](https://travis-ci.org/awslabs/cloudsearchable)
|
3
5
|
|
4
6
|
## Installation
|
5
7
|
Add to your Gemfile: gem 'cloudsearchable'. Run bundle or: gem install cloudsearchable.
|
@@ -15,18 +17,18 @@ class Customer
|
|
15
17
|
# This is the default index. You probably only need one.
|
16
18
|
index_in_cloudsearch do |idx|
|
17
19
|
# Fetch the customer_id field from customer
|
18
|
-
literal :customer_id, :
|
20
|
+
literal :customer_id, :result_enabled => true, :search_enabled => true, :source => Proc.new { customer }
|
19
21
|
|
20
22
|
# Map the 'name' Ruby attribute to a field called 'test_name'
|
21
|
-
text :test_name, :
|
23
|
+
text :test_name, :result_enabled => false, :search_enabled => true, :source => :name
|
22
24
|
|
23
25
|
# uint fields can be used in result ranking functions
|
24
|
-
uint :helpfulness, :
|
26
|
+
uint :helpfulness, :result_enabled => true, :search_enabled => false do; 1234 end
|
25
27
|
end
|
26
28
|
|
27
29
|
# A named index.
|
28
30
|
index_in_cloudsearch :test_index do |idx|
|
29
|
-
literal :id, :
|
31
|
+
literal :id, :search_enabled => true
|
30
32
|
end
|
31
33
|
end
|
32
34
|
```
|
@@ -121,7 +123,7 @@ See spec tests and source code for more information.
|
|
121
123
|
* [Lane LaRue](https://github.com/luxx)
|
122
124
|
* [Philip White](https://github.com/philipmw)
|
123
125
|
|
124
|
-
|
126
|
+
Apache 2.0 License
|
125
127
|
|
126
128
|
## Contributing
|
127
129
|
|
data/Rakefile
CHANGED
data/cloudsearchable.gemspec
CHANGED
@@ -47,9 +47,9 @@ Gem::Specification.new do |spec|
|
|
47
47
|
spec.add_development_dependency "bundler", "~> 1.3"
|
48
48
|
spec.add_development_dependency "rake"
|
49
49
|
spec.add_development_dependency "yard"
|
50
|
-
spec.add_dependency 'aws-sdk'
|
50
|
+
spec.add_dependency 'aws-sdk', "~> 2"
|
51
51
|
|
52
52
|
# testing dependencies
|
53
|
-
spec.add_development_dependency "rspec"
|
53
|
+
spec.add_development_dependency "rspec", '~> 3'
|
54
54
|
spec.add_development_dependency "activemodel"
|
55
55
|
end
|
@@ -5,7 +5,7 @@ module CloudSearch
|
|
5
5
|
API_VERSION = "2011-02-01"
|
6
6
|
|
7
7
|
def self.client
|
8
|
-
@client ||=
|
8
|
+
@client ||= Aws::CloudSearch::Client.new
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.client=(client)
|
@@ -27,8 +27,7 @@ module CloudSearch
|
|
27
27
|
req.body = JSON.generate sdf_list
|
28
28
|
req["Content-Type"] = "application/json"
|
29
29
|
|
30
|
-
|
31
|
-
response = http.start{|http| http.request(req)}
|
30
|
+
response = Net::HTTP.start(uri.host, uri.port){|http| http.request(req)}
|
32
31
|
|
33
32
|
if response.is_a? Net::HTTPSuccess
|
34
33
|
JSON.parse response.body
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'net/http'
|
1
2
|
require 'spec_helper'
|
2
3
|
require 'test_classes/cloud_searchable_test_class'
|
3
4
|
|
@@ -28,17 +29,17 @@ describe CloudSearch do
|
|
28
29
|
let(:success_response){ MockHTTPOK.new( {"status" => "success", "adds" => 1, "deletes" => 0}.to_json ) }
|
29
30
|
|
30
31
|
it 'json parses the response' do
|
31
|
-
Net::HTTP.
|
32
|
+
allow(Net::HTTP).to receive(:start).and_return(success_response)
|
32
33
|
|
33
34
|
response = described_class.post_sdf endpoint, sdf_document
|
34
|
-
response.
|
35
|
+
expect(response).to eq JSON.parse(success_response.body)
|
35
36
|
end
|
36
37
|
|
37
38
|
it 'triggers error! on response its no not a Net::HTTPSuccess' do
|
38
39
|
response = MockHTTPBadRequest.new
|
39
|
-
Net::HTTP.
|
40
|
+
allow(Net::HTTP).to receive(:start).and_return(response)
|
40
41
|
|
41
|
-
response.
|
42
|
+
expect(response).to receive(:error!)
|
42
43
|
described_class.post_sdf endpoint, sdf_document
|
43
44
|
end
|
44
45
|
|
@@ -6,17 +6,17 @@ describe Cloudsearchable do
|
|
6
6
|
|
7
7
|
it 'can describe an index that returns ids for the class type' do
|
8
8
|
test_index = clazz.cloudsearch_index
|
9
|
-
test_index.
|
10
|
-
test_index.fields.
|
9
|
+
expect(test_index).to be_a(Cloudsearchable::Domain)
|
10
|
+
expect(test_index.fields.count).to eq 4 #3 explicit + 1 for the id of the object
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'has a default index' do
|
14
|
-
clazz.cloudsearch_index.
|
15
|
-
clazz.cloudsearch_index(:test_index).
|
14
|
+
expect(clazz.cloudsearch_index).to be_a(Cloudsearchable::Domain)
|
15
|
+
expect(clazz.cloudsearch_index(:test_index)).to_not eq(clazz.cloudsearch_index)
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'names domains consistent with CloudSearch limitations' do
|
19
|
-
clazz.cloudsearch_index(:test_index).name.
|
19
|
+
expect(clazz.cloudsearch_index(:test_index).name).to be =~ /^[a-z][a-z0-9\-]+$/
|
20
20
|
end
|
21
21
|
|
22
22
|
describe 'an ordinary object' do
|
@@ -34,21 +34,21 @@ describe Cloudsearchable do
|
|
34
34
|
|
35
35
|
it 'supplies the right values to the fields' do
|
36
36
|
test_index = clazz.cloudsearch_index
|
37
|
-
test_index.fields[:test_class_id].value_for(inst).
|
38
|
-
test_index.fields[:customer_id].value_for(inst).
|
39
|
-
test_index.fields[:test_name].value_for(inst).
|
40
|
-
test_index.fields[:helpfulness].value_for(inst).
|
37
|
+
expect(test_index.fields[:test_class_id].value_for(inst)).to eq(inst.id)
|
38
|
+
expect(test_index.fields[:customer_id].value_for(inst)).to eq(inst.customer)
|
39
|
+
expect(test_index.fields[:test_name].value_for(inst)).to eq (inst.name)
|
40
|
+
expect(test_index.fields[:helpfulness].value_for(inst)).to eq(1234)
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'reindexes when told to' do
|
44
|
-
clazz.cloudsearch_index( ).
|
45
|
-
clazz.cloudsearch_index(:test_index).
|
44
|
+
expect(clazz.cloudsearch_index( )).to receive(:post_record).with(inst, inst.id, inst.lock_version)
|
45
|
+
expect(clazz.cloudsearch_index(:test_index)).to receive(:post_record).with(inst, inst.id, inst.lock_version)
|
46
46
|
inst.update_indexes
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'generates a sensible addition sdf document' do
|
50
50
|
sdf = clazz.cloudsearch_index.send :addition_sdf, inst, inst.id, inst.lock_version
|
51
|
-
sdf[:fields][:helpfulness].
|
51
|
+
expect(sdf[:fields][:helpfulness]).to eq(1234)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -62,8 +62,8 @@ describe Cloudsearchable do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'reindexes when told to' do
|
65
|
-
clazz.cloudsearch_index( ).
|
66
|
-
clazz.cloudsearch_index(:test_index).
|
65
|
+
expect(clazz.cloudsearch_index( )).to receive(:delete_record).with(inst.id, inst.lock_version)
|
66
|
+
expect(clazz.cloudsearch_index(:test_index)).to receive(:delete_record).with(inst.id, inst.lock_version)
|
67
67
|
inst.update_indexes
|
68
68
|
end
|
69
69
|
end
|
@@ -16,25 +16,25 @@ describe Cloudsearchable::Config::Options do
|
|
16
16
|
|
17
17
|
it 'sets and gets' do
|
18
18
|
subject.foo = 5
|
19
|
-
subject.foo.
|
19
|
+
expect(subject.foo).to eq 5
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'defaults' do
|
23
|
-
subject.warnings.
|
24
|
-
subject.warnings.
|
23
|
+
expect(subject.warnings).to_not be_nil
|
24
|
+
expect(subject.warnings).to eq subject.settings[:warnings]
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'resets option' do
|
28
28
|
subject.timezone = "EST"
|
29
|
-
subject.timezone.
|
29
|
+
expect(subject.timezone).to eq "EST"
|
30
30
|
subject.reset_timezone
|
31
|
-
subject.timezone.
|
31
|
+
expect(subject.timezone).to eq "PST"
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'resets all options' do
|
35
35
|
subject.foo = 5
|
36
36
|
subject.reset
|
37
|
-
subject.foo.
|
37
|
+
expect(subject.foo).to be_nil
|
38
38
|
end
|
39
39
|
|
40
40
|
end
|
@@ -6,10 +6,10 @@ describe Cloudsearchable::Config do
|
|
6
6
|
config.domain_prefix = 'dev-llarue-'
|
7
7
|
end
|
8
8
|
|
9
|
-
Cloudsearchable.configure.domain_prefix.
|
9
|
+
expect(Cloudsearchable.configure.domain_prefix).to eq 'dev-llarue-'
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'aliases configure to config' do
|
13
|
-
Cloudsearchable.config.domain_prefix.
|
13
|
+
expect(Cloudsearchable.config.domain_prefix).to eq Cloudsearchable.configure.domain_prefix
|
14
14
|
end
|
15
15
|
end
|
@@ -4,7 +4,7 @@ require 'test_classes/cloud_searchable_test_class'
|
|
4
4
|
describe Cloudsearchable::Domain do
|
5
5
|
before(:each) do
|
6
6
|
fake_client = double('client')
|
7
|
-
CloudSearch.
|
7
|
+
allow(CloudSearch).to receive(:client).and_return(fake_client)
|
8
8
|
end
|
9
9
|
|
10
10
|
#
|
@@ -15,7 +15,7 @@ describe Cloudsearchable::Domain do
|
|
15
15
|
let(:needs_rebuild_domain) do
|
16
16
|
described_class.new('nrb-index').tap do |dom|
|
17
17
|
resp = describe_domain_response(dom.name)
|
18
|
-
CloudSearch.client.
|
18
|
+
allow(CloudSearch.client).to receive(:describe_domains).with(:domain_names => [dom.name]).
|
19
19
|
and_return(
|
20
20
|
describe_domain_response(dom.name, :required_index_documents => true),
|
21
21
|
describe_domain_response(dom.name, :processing => true),
|
@@ -27,26 +27,26 @@ describe Cloudsearchable::Domain do
|
|
27
27
|
# A domain name named 'my-index'
|
28
28
|
let(:domain) do
|
29
29
|
described_class.new('my-index').tap do |dom|
|
30
|
-
CloudSearch.client.
|
31
|
-
CloudSearch.client.
|
30
|
+
allow(CloudSearch.client).to receive(:describe_domains).and_return(describe_domain_response(dom.name))
|
31
|
+
allow(CloudSearch.client).to receive(:describe_domains).with(:domain_names => [dom.name]).and_return(describe_domain_response(dom.name))
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
let(:empty_domain) do
|
36
36
|
described_class.new('my-index').tap do |dom|
|
37
|
-
CloudSearch.client.
|
37
|
+
allow(CloudSearch.client).to receive(:describe_domains).and_return({})
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'can be instantiated' do
|
42
42
|
index = domain
|
43
|
-
index.name.
|
43
|
+
expect(index.name).to end_with('my-index')
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'can haz a literal field' do
|
47
47
|
index = domain
|
48
48
|
index.add_field(:literary, :literal) { nil }
|
49
|
-
index.fields[:literary].type.
|
49
|
+
expect(index.fields[:literary].type).to eq(:literal)
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'can be initialized with a nested class' do
|
@@ -56,7 +56,7 @@ describe Cloudsearchable::Domain do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
OuterClassForCloudSearch::InnerClass.cloudsearch_prefix.
|
59
|
+
expect(OuterClassForCloudSearch::InnerClass.cloudsearch_prefix).to match(/^[A-Za-z0-9_-]+$/)
|
60
60
|
Object.instance_eval { remove_const :OuterClassForCloudSearch }
|
61
61
|
end
|
62
62
|
|
@@ -69,12 +69,12 @@ describe Cloudsearchable::Domain do
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
it "
|
73
|
-
subject.addition_sdf(object, "id", 1)[:fields][:field_with_present_value].
|
72
|
+
it "generates present fields" do
|
73
|
+
expect(subject.addition_sdf(object, "id", 1)[:fields][:field_with_present_value]).to eq 42
|
74
74
|
end
|
75
75
|
|
76
|
-
it "
|
77
|
-
subject.addition_sdf(object, "id", 1)[:fields][:field_with_nil_value].
|
76
|
+
it "does not generate nil fields" do
|
77
|
+
expect(subject.addition_sdf(object, "id", 1)[:fields][:field_with_nil_value]).to be_nil
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -88,18 +88,18 @@ describe Cloudsearchable::Domain do
|
|
88
88
|
# on a class variable
|
89
89
|
#
|
90
90
|
it 'caches endpoints for multiple domains' do
|
91
|
-
domain.send(:search_endpoint).
|
91
|
+
expect(domain.send(:search_endpoint)).to_not eq(needs_rebuild_domain.send(:search_endpoint))
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'endpoint selected is based on the domain name' do
|
95
|
-
domain.send(:search_endpoint).
|
96
|
-
domain.send(:doc_endpoint).
|
95
|
+
expect(domain.send(:search_endpoint)).to eq describe_domain_response(domain.name)[:domain_status_list][0][:search_service][:endpoint]
|
96
|
+
expect(domain.send(:doc_endpoint)).to eq describe_domain_response(domain.name)[:domain_status_list][0][:doc_service][:endpoint]
|
97
97
|
end
|
98
98
|
|
99
99
|
it 'sleeps, waiting for reindexing' do
|
100
|
-
CloudSearch.client.
|
101
|
-
CloudSearch.client.
|
102
|
-
needs_rebuild_domain.apply_changes(3).
|
100
|
+
expect(CloudSearch.client).to receive(:index_documents).with(:domain_name => needs_rebuild_domain.name)
|
101
|
+
expect(CloudSearch.client).to receive(:describe_domains).exactly(3).times
|
102
|
+
expect(needs_rebuild_domain.apply_changes(3)).to be_truthy
|
103
103
|
end
|
104
104
|
|
105
105
|
protected
|
@@ -2,28 +2,32 @@ require 'spec_helper'
|
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
4
|
describe Cloudsearchable::Field do
|
5
|
+
before :all do
|
6
|
+
ENV['AWS_REGION'] = 'us-east-1'
|
7
|
+
end
|
8
|
+
|
5
9
|
it 'has a name' do
|
6
10
|
field = described_class.new 'fnord', :literal
|
7
|
-
field.name.
|
11
|
+
expect(field.name).to eq(:fnord)
|
8
12
|
end
|
9
13
|
|
10
14
|
it 'can find its value' do
|
11
15
|
test_value = nil
|
12
16
|
field = described_class.new('foo', :literal, :source => Proc.new { test_value })
|
13
17
|
test_value = 123
|
14
|
-
field.value_for(Object.new).
|
18
|
+
expect(field.value_for(Object.new)).to eq(test_value)
|
15
19
|
|
16
20
|
record = OpenStruct.new :a => test_value
|
17
21
|
field2 = described_class.new('bar', :literal, :source => :a)
|
18
|
-
field.value_for(record).
|
22
|
+
expect(field.value_for(record)).to eq(test_value)
|
19
23
|
end
|
20
24
|
|
21
25
|
it 'generates a field definition' do
|
22
26
|
domain_name = 'narnia'
|
23
27
|
field = described_class.new('fnord', :literal, :search_enabled => true)
|
24
|
-
CloudSearch.client.
|
25
|
-
call[:domain_name].
|
26
|
-
call[:index_field][:literal_options][:search_enabled].
|
28
|
+
expect(CloudSearch.client).to receive(:define_index_field) do |call|
|
29
|
+
expect(call[:domain_name]).to eq(domain_name)
|
30
|
+
expect(call[:index_field][:literal_options][:search_enabled]).to be_truthy
|
27
31
|
end
|
28
32
|
field.define_in_domain domain_name
|
29
33
|
end
|
@@ -12,7 +12,7 @@ describe Cloudsearchable::Query do
|
|
12
12
|
|
13
13
|
describe '#where' do
|
14
14
|
it 'can build a simple search query' do
|
15
|
-
clazz.search.where(:customer_id, :eq, 'A1234').query.to_q[:bq].
|
15
|
+
expect(clazz.search.where(:customer_id, :eq, 'A1234').query.to_q[:bq]).to be =~ /customer_id:'A1234'/
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'rejects field names that were not defined in the index' do
|
@@ -21,31 +21,31 @@ describe Cloudsearchable::Query do
|
|
21
21
|
|
22
22
|
it 'chains' do
|
23
23
|
query = clazz.search.where(customer_id: 'A1234').where(helpfulness: 42).query.to_q[:bq]
|
24
|
-
query.
|
25
|
-
query.
|
24
|
+
expect(query).to be =~ /customer_id:'A1234'/
|
25
|
+
expect(query).to be =~ /helpfulness:42/
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'can build a query with "not equal to" condition' do
|
29
|
-
|
29
|
+
expect(clazz.search.where(:customer_id, :!=, 'A1234').query.to_q[:bq]).to be =~ /\(not customer_id:'A1234'\)/
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'can build a query from a hash' do
|
33
33
|
query = clazz.search.where(customer_id: 'A1234', helpfulness: 42).query.to_q[:bq]
|
34
|
-
query.
|
35
|
-
query.
|
34
|
+
expect(query).to be =~ /customer_id:'A1234'/
|
35
|
+
expect(query).to be =~ /helpfulness:42/
|
36
36
|
end
|
37
37
|
|
38
38
|
context 'literal data type' do
|
39
39
|
it 'supports equality' do
|
40
|
-
clazz.search.where(:customer_id, :==, 'ABC').query.to_q[:bq].
|
40
|
+
expect(clazz.search.where(:customer_id, :==, 'ABC').query.to_q[:bq]).to eq "customer_id:'ABC'"
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'supports :any' do
|
44
|
-
clazz.search.where(:customer_id, :any, ['ABC', 'DEF']).query.to_q[:bq].
|
44
|
+
expect(clazz.search.where(:customer_id, :any, ['ABC', 'DEF']).query.to_q[:bq]).to eq "(or customer_id:'ABC' customer_id:'DEF')"
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'accepts a value as an integer' do
|
48
|
-
clazz.search.where(customer_id: 123).query.to_q[:bq].
|
48
|
+
expect(clazz.search.where(customer_id: 123).query.to_q[:bq]).to be =~ /customer_id:'123'/
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'rejects nil value' do
|
@@ -55,43 +55,43 @@ describe Cloudsearchable::Query do
|
|
55
55
|
|
56
56
|
context 'uint data type' do
|
57
57
|
it 'supports range query' do
|
58
|
-
clazz.search.where(:helpfulness, :within_range, "0..#{123}").query.to_q[:bq].
|
58
|
+
expect(clazz.search.where(:helpfulness, :within_range, "0..#{123}").query.to_q[:bq]).to be =~ /helpfulness:0..123/
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'supports range query using a ruby range' do
|
62
|
-
clazz.search.where(:helpfulness, :within_range, 0..123).query.to_q[:bq].
|
62
|
+
expect(clazz.search.where(:helpfulness, :within_range, 0..123).query.to_q[:bq]).to be =~ /helpfulness:0..123/
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'supports equality' do
|
66
|
-
clazz.search.where(:helpfulness, :==, 123).query.to_q[:bq].
|
66
|
+
expect(clazz.search.where(:helpfulness, :==, 123).query.to_q[:bq]).to eq 'helpfulness:123'
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'supports not-equality' do
|
70
|
-
clazz.search.where(:helpfulness, :!=, 123).query.to_q[:bq].
|
70
|
+
expect(clazz.search.where(:helpfulness, :!=, 123).query.to_q[:bq]).to eq '(not helpfulness:123)'
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'supports greater-than' do
|
74
|
-
clazz.search.where(:helpfulness, :>, 123).query.to_q[:bq].
|
74
|
+
expect(clazz.search.where(:helpfulness, :>, 123).query.to_q[:bq]).to be =~ /helpfulness:124../
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'supports greater-than-or-equal-to' do
|
78
|
-
clazz.search.where(:helpfulness, :>=, 123).query.to_q[:bq].
|
78
|
+
expect(clazz.search.where(:helpfulness, :>=, 123).query.to_q[:bq]).to be =~ /helpfulness:123../
|
79
79
|
end
|
80
80
|
|
81
81
|
it 'supports less-than' do
|
82
|
-
clazz.search.where(:helpfulness, :<, 123).query.to_q[:bq].
|
82
|
+
expect(clazz.search.where(:helpfulness, :<, 123).query.to_q[:bq]).to be =~ /helpfulness:..122/
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'supports less-than-or-equal-to' do
|
86
|
-
clazz.search.where(:helpfulness, :<=, 123).query.to_q[:bq].
|
86
|
+
expect(clazz.search.where(:helpfulness, :<=, 123).query.to_q[:bq]).to be =~ /helpfulness:..123/
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'supports :any' do
|
90
|
-
clazz.search.where(:helpfulness, :any, [123, 456]).query.to_q[:bq].
|
90
|
+
expect(clazz.search.where(:helpfulness, :any, [123, 456]).query.to_q[:bq]).to eq '(or helpfulness:123 helpfulness:456)'
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'accepts a value as a string' do
|
94
|
-
clazz.search.where(helpfulness: '123').query.to_q[:bq].
|
94
|
+
expect(clazz.search.where(helpfulness: '123').query.to_q[:bq]).to be =~ /helpfulness:123/
|
95
95
|
end
|
96
96
|
|
97
97
|
[Object.new, nil, '123a'].each do |v|
|
@@ -112,45 +112,45 @@ describe Cloudsearchable::Query do
|
|
112
112
|
|
113
113
|
|
114
114
|
it 'supports querying for any of several values of a field' do
|
115
|
-
clazz.search.where(:test_name, :any, %w{big small}).query.to_q[:bq].
|
115
|
+
expect(clazz.search.where(:test_name, :any, %w{big small}).query.to_q[:bq]).to include("(or test_name:'big' test_name:'small')")
|
116
116
|
end
|
117
117
|
|
118
118
|
it 'supports text method' do
|
119
119
|
query = clazz.search.text('test').query.to_q[:q]
|
120
|
-
query.
|
120
|
+
expect(query).to be =~ /test/
|
121
121
|
end
|
122
122
|
|
123
123
|
it 'supports chaining text and where clauses together' do
|
124
124
|
query = clazz.search.text('test').where(:helpfulness, :==, 123).query
|
125
|
-
query.to_q[:q].
|
126
|
-
query.to_q[:bq].
|
125
|
+
expect(query.to_q[:q]).to be =~ /test/
|
126
|
+
expect(query.to_q[:bq]).to be =~ /helpfulness:123/
|
127
127
|
end
|
128
128
|
|
129
129
|
it 'supports ordering with a rank expression' do
|
130
|
-
clazz.search.where(customer_id: 12345).order('-helpfulness').query.to_q[:rank].
|
130
|
+
expect(clazz.search.where(customer_id: 12345).order('-helpfulness').query.to_q[:rank]).to eq '-helpfulness'
|
131
131
|
end
|
132
132
|
|
133
133
|
it 'supports limit' do
|
134
|
-
clazz.search.where(customer_id: 12345).limit(10).query.to_q[:size].
|
134
|
+
expect(clazz.search.where(customer_id: 12345).limit(10).query.to_q[:size]).to eq 10
|
135
135
|
end
|
136
136
|
|
137
137
|
it 'has high default limit' do
|
138
|
-
clazz.search.where(customer_id: 12345).query.to_q[:size].
|
138
|
+
expect(clazz.search.where(customer_id: 12345).query.to_q[:size]).to eq 100000
|
139
139
|
end
|
140
140
|
|
141
141
|
it 'supports offset' do
|
142
|
-
clazz.search.where(customer_id: 12345).offset(100).query.to_q[:start].
|
142
|
+
expect(clazz.search.where(customer_id: 12345).offset(100).query.to_q[:start]).to eq 100
|
143
143
|
end
|
144
144
|
|
145
145
|
context 'queries' do
|
146
146
|
before(:each) do
|
147
|
-
clazz.cloudsearch_index.
|
147
|
+
expect(clazz.cloudsearch_index).to receive(:execute_query).and_return(cloudsearch_response)
|
148
148
|
end
|
149
149
|
|
150
150
|
context 'query warning' do
|
151
151
|
before(:each) do
|
152
|
-
clazz.
|
153
|
-
Cloudsearchable.logger.
|
152
|
+
allow(clazz).to receive(:find).and_return([])
|
153
|
+
expect(Cloudsearchable.logger).to receive(:warn).with(/CS-InvalidFieldOrRankAliasInRankParameter/)
|
154
154
|
end
|
155
155
|
|
156
156
|
let(:query){clazz.search.where(customer_id: 12345).order("-adult")}
|
@@ -192,16 +192,16 @@ describe Cloudsearchable::Query do
|
|
192
192
|
end
|
193
193
|
|
194
194
|
it 'causes WarningInQueryResult exception' do
|
195
|
-
|
195
|
+
expect{ query.to_a }.to raise_error(Cloudsearchable::WarningInQueryResult)
|
196
196
|
end
|
197
197
|
|
198
198
|
it 'takes a :fatal_warnings option, and when set to false, does not raise' do
|
199
199
|
sample_query = Cloudsearchable::QueryChain.new(double, fatal_warnings: false)
|
200
|
-
sample_query.instance_variable_get(:@fatal_warnings).
|
200
|
+
expect(sample_query.instance_variable_get(:@fatal_warnings)).to be_falsey
|
201
201
|
|
202
202
|
q = query
|
203
203
|
q.query.instance_variable_set(:@fatal_warnings, false)
|
204
|
-
|
204
|
+
expect{ q.to_a }.to_not raise_error
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
@@ -238,55 +238,55 @@ describe Cloudsearchable::Query do
|
|
238
238
|
end
|
239
239
|
|
240
240
|
it 'materializes' do
|
241
|
-
clazz.
|
241
|
+
expect(clazz).to receive(:find).with(["ANINSTANCEID"]).and_return([customer_id])
|
242
242
|
query = clazz.search.where(customer_id: 12345)
|
243
|
-
query.to_a.
|
243
|
+
expect(query.to_a).to eq [customer_id]
|
244
244
|
end
|
245
245
|
|
246
246
|
it 'materializes db results only once' do
|
247
247
|
expected_results = [customer_id, other_customer_id]
|
248
|
-
clazz.
|
248
|
+
expect(clazz).to receive(:find).once.and_return(expected_results)
|
249
249
|
|
250
250
|
query = clazz.search.where(customer_id: 12345)
|
251
251
|
query.materialize!
|
252
252
|
query.materialize!
|
253
253
|
end
|
254
254
|
|
255
|
-
it '
|
256
|
-
clazz.
|
255
|
+
it 'does not materialize if only asking for found_count' do
|
256
|
+
expect(clazz).to_not receive(:find)
|
257
257
|
clazz.search.where(customer_id: 12345).found_count
|
258
258
|
end
|
259
259
|
|
260
260
|
it 'supports each for multiple results' do
|
261
261
|
expected_results = [customer_id, other_customer_id]
|
262
|
-
clazz.
|
262
|
+
expect(clazz).to receive(:find).with(["ANINSTANCEID"]).and_return(expected_results)
|
263
263
|
|
264
264
|
results = clazz.search.where(customer_id: 12345).to_a
|
265
|
-
(0..results.length).each{ |i| results[i].
|
265
|
+
(0..results.length).each{ |i| expect(results[i]).to eq expected_results[i] }
|
266
266
|
end
|
267
267
|
|
268
268
|
it 'supports each for single results' do
|
269
|
-
clazz.
|
269
|
+
expect(clazz).to receive(:find).with(["ANINSTANCEID"]).and_return(customer_id)
|
270
270
|
|
271
271
|
results = clazz.search.where(customer_id: 12345).to_a
|
272
|
-
results.each{ |r| r.
|
272
|
+
results.each{ |r| expect(r).to eq customer_id }
|
273
273
|
end
|
274
274
|
|
275
275
|
it 'supports each for nil result' do
|
276
|
-
clazz.
|
276
|
+
expect(clazz).to receive(:find).with(["ANINSTANCEID"]).and_return(nil)
|
277
277
|
|
278
278
|
results = clazz.search.where(customer_id: 12345).to_a
|
279
|
-
results.each{ |r| r.
|
279
|
+
results.each{ |r| expect(r).to be_nil }
|
280
280
|
end
|
281
281
|
|
282
282
|
it 'uses materialized method' do
|
283
|
-
clazz.
|
283
|
+
expect(clazz).to receive(:another_find).with(["ANINSTANCEID"]).and_return(customer_id)
|
284
284
|
clazz.materialize_method :another_find
|
285
285
|
clazz.search.where(customer_id: 12345).to_a
|
286
286
|
end
|
287
287
|
|
288
288
|
it 'returns the correct found count' do
|
289
|
-
clazz.search.where(customer_id: 12345).found_count.
|
289
|
+
expect(clazz.search.where(customer_id: 12345).found_count).to eq 11
|
290
290
|
end
|
291
291
|
end
|
292
292
|
|
@@ -335,7 +335,7 @@ describe Cloudsearchable::Query do
|
|
335
335
|
end
|
336
336
|
|
337
337
|
it 'does not raise an exception' do
|
338
|
-
clazz.
|
338
|
+
expect(clazz).to receive(:find).with([]).and_return(nil)
|
339
339
|
clazz.search.where(:customer_id, :!=, 'ABCDE')
|
340
340
|
expect { clazz.search.where(:customer_id, :!=, 'ABCDE').to_a }.to_not raise_error
|
341
341
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -25,18 +25,18 @@ CloudSearchableSampleClassFactory = Proc.new do
|
|
25
25
|
# This is the default index. You probably only need one.
|
26
26
|
index_in_cloudsearch do |idx|
|
27
27
|
# Fetch the customer_id field from customer
|
28
|
-
literal :customer_id, :
|
28
|
+
literal :customer_id, :result_enabled => true, :search_enabled => true, :source => Proc.new { customer }
|
29
29
|
|
30
30
|
# Map the 'name' Ruby attribute to a field called 'test_name'
|
31
|
-
text :test_name, :
|
31
|
+
text :test_name, :result_enabled => false, :search_enabled => true, :source => :name
|
32
32
|
|
33
33
|
# uint fields can be used in result ranking functions
|
34
|
-
uint :helpfulness, :
|
34
|
+
uint :helpfulness, :result_enabled => true, :search_enabled => false do; 1234 end
|
35
35
|
end
|
36
36
|
|
37
37
|
# A named index.
|
38
38
|
index_in_cloudsearch :test_index do |idx|
|
39
|
-
literal :id, :
|
39
|
+
literal :id, :search_enabled => true
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
metadata
CHANGED
@@ -1,110 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudsearchable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Lane LaRue
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-11-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '1.3'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '1.3'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: yard
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: aws-sdk
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - "~>"
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
61
|
+
version: '2'
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - "~>"
|
76
67
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
68
|
+
version: '2'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rspec
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - "~>"
|
84
74
|
- !ruby/object:Gem::Version
|
85
|
-
version: '
|
75
|
+
version: '3'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - "~>"
|
92
81
|
- !ruby/object:Gem::Version
|
93
|
-
version: '
|
82
|
+
version: '3'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: activemodel
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ">="
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
description: ActiveRecord-like query interface for AWS Cloud Search
|
@@ -114,7 +101,7 @@ executables: []
|
|
114
101
|
extensions: []
|
115
102
|
extra_rdoc_files: []
|
116
103
|
files:
|
117
|
-
- .rspec
|
104
|
+
- ".rspec"
|
118
105
|
- Gemfile
|
119
106
|
- LICENSE.txt
|
120
107
|
- README.md
|
@@ -140,27 +127,26 @@ files:
|
|
140
127
|
homepage: ''
|
141
128
|
licenses:
|
142
129
|
- MIT
|
130
|
+
metadata: {}
|
143
131
|
post_install_message:
|
144
132
|
rdoc_options: []
|
145
133
|
require_paths:
|
146
134
|
- lib
|
147
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
-
none: false
|
149
136
|
requirements:
|
150
|
-
- -
|
137
|
+
- - ">="
|
151
138
|
- !ruby/object:Gem::Version
|
152
139
|
version: '0'
|
153
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
-
none: false
|
155
141
|
requirements:
|
156
|
-
- -
|
142
|
+
- - ">="
|
157
143
|
- !ruby/object:Gem::Version
|
158
144
|
version: '0'
|
159
145
|
requirements: []
|
160
146
|
rubyforge_project:
|
161
|
-
rubygems_version:
|
147
|
+
rubygems_version: 2.4.5.1
|
162
148
|
signing_key:
|
163
|
-
specification_version:
|
149
|
+
specification_version: 4
|
164
150
|
summary: ActiveRecord-like query interface for AWS Cloud Search
|
165
151
|
test_files:
|
166
152
|
- spec/cloudsearchable/cloud_search_spec.rb
|
@@ -172,4 +158,3 @@ test_files:
|
|
172
158
|
- spec/cloudsearchable/query_chain_spec.rb
|
173
159
|
- spec/spec_helper.rb
|
174
160
|
- spec/test_classes/cloud_searchable_test_class.rb
|
175
|
-
has_rdoc:
|