elasticsearch-model-queryable 0.1.5
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 +20 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +695 -0
- data/Rakefile +59 -0
- data/elasticsearch-model.gemspec +57 -0
- data/examples/activerecord_article.rb +77 -0
- data/examples/activerecord_associations.rb +162 -0
- data/examples/couchbase_article.rb +66 -0
- data/examples/datamapper_article.rb +71 -0
- data/examples/mongoid_article.rb +68 -0
- data/examples/ohm_article.rb +70 -0
- data/examples/riak_article.rb +52 -0
- data/gemfiles/3.0.gemfile +12 -0
- data/gemfiles/4.0.gemfile +11 -0
- data/lib/elasticsearch/model/adapter.rb +145 -0
- data/lib/elasticsearch/model/adapters/active_record.rb +104 -0
- data/lib/elasticsearch/model/adapters/default.rb +50 -0
- data/lib/elasticsearch/model/adapters/mongoid.rb +92 -0
- data/lib/elasticsearch/model/callbacks.rb +35 -0
- data/lib/elasticsearch/model/client.rb +61 -0
- data/lib/elasticsearch/model/ext/active_record.rb +14 -0
- data/lib/elasticsearch/model/hash_wrapper.rb +15 -0
- data/lib/elasticsearch/model/importing.rb +144 -0
- data/lib/elasticsearch/model/indexing.rb +472 -0
- data/lib/elasticsearch/model/naming.rb +101 -0
- data/lib/elasticsearch/model/proxy.rb +127 -0
- data/lib/elasticsearch/model/response/base.rb +44 -0
- data/lib/elasticsearch/model/response/pagination.rb +173 -0
- data/lib/elasticsearch/model/response/records.rb +69 -0
- data/lib/elasticsearch/model/response/result.rb +63 -0
- data/lib/elasticsearch/model/response/results.rb +31 -0
- data/lib/elasticsearch/model/response.rb +71 -0
- data/lib/elasticsearch/model/searching.rb +107 -0
- data/lib/elasticsearch/model/serializing.rb +35 -0
- data/lib/elasticsearch/model/version.rb +5 -0
- data/lib/elasticsearch/model.rb +157 -0
- data/test/integration/active_record_associations_parent_child.rb +139 -0
- data/test/integration/active_record_associations_test.rb +307 -0
- data/test/integration/active_record_basic_test.rb +179 -0
- data/test/integration/active_record_custom_serialization_test.rb +62 -0
- data/test/integration/active_record_import_test.rb +100 -0
- data/test/integration/active_record_namespaced_model_test.rb +49 -0
- data/test/integration/active_record_pagination_test.rb +132 -0
- data/test/integration/mongoid_basic_test.rb +193 -0
- data/test/test_helper.rb +63 -0
- data/test/unit/adapter_active_record_test.rb +140 -0
- data/test/unit/adapter_default_test.rb +41 -0
- data/test/unit/adapter_mongoid_test.rb +102 -0
- data/test/unit/adapter_test.rb +69 -0
- data/test/unit/callbacks_test.rb +31 -0
- data/test/unit/client_test.rb +27 -0
- data/test/unit/importing_test.rb +176 -0
- data/test/unit/indexing_test.rb +478 -0
- data/test/unit/module_test.rb +57 -0
- data/test/unit/naming_test.rb +76 -0
- data/test/unit/proxy_test.rb +89 -0
- data/test/unit/response_base_test.rb +40 -0
- data/test/unit/response_pagination_kaminari_test.rb +189 -0
- data/test/unit/response_pagination_will_paginate_test.rb +208 -0
- data/test/unit/response_records_test.rb +91 -0
- data/test/unit/response_result_test.rb +90 -0
- data/test/unit/response_results_test.rb +31 -0
- data/test/unit/response_test.rb +67 -0
- data/test/unit/searching_search_request_test.rb +78 -0
- data/test/unit/searching_test.rb +41 -0
- data/test/unit/serializing_test.rb +17 -0
- metadata +466 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::RecordsTest < Test::Unit::TestCase
|
4
|
+
context "Response records" do
|
5
|
+
class DummyCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def each(&block); ['FOO'].each(&block); end
|
9
|
+
def size; ['FOO'].size; end
|
10
|
+
def empty?; ['FOO'].empty?; end
|
11
|
+
def foo; 'BAR'; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DummyModel
|
15
|
+
def self.index_name; 'foo'; end
|
16
|
+
def self.document_type; 'bar'; end
|
17
|
+
|
18
|
+
def self.find(*args)
|
19
|
+
DummyCollection.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'_id' => '1', 'foo' => 'bar'}] } }
|
24
|
+
RESULTS = Elasticsearch::Model::Response::Results.new DummyModel, RESPONSE
|
25
|
+
|
26
|
+
setup do
|
27
|
+
search = Elasticsearch::Model::Searching::SearchRequest.new DummyModel, '*'
|
28
|
+
search.stubs(:execute!).returns RESPONSE
|
29
|
+
|
30
|
+
response = Elasticsearch::Model::Response::Response.new DummyModel, search
|
31
|
+
@records = Elasticsearch::Model::Response::Records.new DummyModel, response
|
32
|
+
end
|
33
|
+
|
34
|
+
should "access the records" do
|
35
|
+
assert_respond_to @records, :records
|
36
|
+
assert_equal 1, @records.records.size
|
37
|
+
assert_equal 'FOO', @records.records.first
|
38
|
+
end
|
39
|
+
|
40
|
+
should "delegate Enumerable methods to records" do
|
41
|
+
assert ! @records.empty?
|
42
|
+
assert_equal 'FOO', @records.first
|
43
|
+
end
|
44
|
+
|
45
|
+
should "delegate methods to records" do
|
46
|
+
assert_respond_to @records, :foo
|
47
|
+
assert_equal 'BAR', @records.foo
|
48
|
+
end
|
49
|
+
|
50
|
+
should "have each_with_hit method" do
|
51
|
+
@records.each_with_hit do |record, hit|
|
52
|
+
assert_equal 'FOO', record
|
53
|
+
assert_equal 'bar', hit.foo
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
should "have map_with_hit method" do
|
58
|
+
assert_equal ['FOO---bar'], @records.map_with_hit { |record, hit| "#{record}---#{hit.foo}" }
|
59
|
+
end
|
60
|
+
|
61
|
+
should "return the IDs" do
|
62
|
+
assert_equal ['1'], @records.ids
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with adapter" do
|
66
|
+
module DummyAdapter
|
67
|
+
module RecordsMixin
|
68
|
+
def records
|
69
|
+
['FOOBAR']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def records_mixin
|
74
|
+
RecordsMixin
|
75
|
+
end; module_function :records_mixin
|
76
|
+
end
|
77
|
+
|
78
|
+
should "delegate the records method to the adapter" do
|
79
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
80
|
+
.with(DummyModel)
|
81
|
+
.returns(DummyAdapter)
|
82
|
+
|
83
|
+
@records = Elasticsearch::Model::Response::Records.new DummyModel,
|
84
|
+
RESPONSE
|
85
|
+
|
86
|
+
assert_equal ['FOOBAR'], @records.records
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
|
4
|
+
context "Response result" do
|
5
|
+
|
6
|
+
should "have method access to properties" do
|
7
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', bar: { bam: 'baz' }
|
8
|
+
|
9
|
+
assert_respond_to result, :foo
|
10
|
+
assert_respond_to result, :bar
|
11
|
+
|
12
|
+
assert_equal 'bar', result.foo
|
13
|
+
assert_equal 'baz', result.bar.bam
|
14
|
+
|
15
|
+
assert_raise(NoMethodError) { result.xoxo }
|
16
|
+
end
|
17
|
+
|
18
|
+
should "return _id as #id" do
|
19
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _id: 42, _source: { id: 12 }
|
20
|
+
|
21
|
+
assert_equal 42, result.id
|
22
|
+
assert_equal 12, result._source.id
|
23
|
+
end
|
24
|
+
|
25
|
+
should "return _type as #type" do
|
26
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _type: 'baz', _source: { type: 'BAM' }
|
27
|
+
|
28
|
+
assert_equal 'baz', result.type
|
29
|
+
assert_equal 'BAM', result._source.type
|
30
|
+
end
|
31
|
+
|
32
|
+
should "delegate method calls to `_source` when available" do
|
33
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'baz' }
|
34
|
+
|
35
|
+
assert_respond_to result, :foo
|
36
|
+
assert_respond_to result, :_source
|
37
|
+
assert_respond_to result, :bar
|
38
|
+
|
39
|
+
assert_equal 'bar', result.foo
|
40
|
+
assert_equal 'baz', result._source.bar
|
41
|
+
assert_equal 'baz', result.bar
|
42
|
+
end
|
43
|
+
|
44
|
+
should "delegate existence method calls to `_source`" do
|
45
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: { bam: 'baz' } }
|
46
|
+
|
47
|
+
assert_respond_to result._source, :bar?
|
48
|
+
assert_respond_to result, :bar?
|
49
|
+
|
50
|
+
assert_equal true, result._source.bar?
|
51
|
+
assert_equal true, result.bar?
|
52
|
+
assert_equal false, result.boo?
|
53
|
+
|
54
|
+
assert_equal true, result.bar.bam?
|
55
|
+
assert_equal false, result.bar.boo?
|
56
|
+
end
|
57
|
+
|
58
|
+
should "delegate methods to @result" do
|
59
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar'
|
60
|
+
|
61
|
+
assert_equal 'bar', result.foo
|
62
|
+
assert_equal 'bar', result.fetch('foo')
|
63
|
+
assert_equal 'moo', result.fetch('NOT_EXIST', 'moo')
|
64
|
+
assert_equal ['foo'], result.keys
|
65
|
+
|
66
|
+
assert_respond_to result, :to_hash
|
67
|
+
assert_equal({'foo' => 'bar'}, result.to_hash)
|
68
|
+
|
69
|
+
assert_raise(NoMethodError) { result.does_not_exist }
|
70
|
+
end
|
71
|
+
|
72
|
+
should "delegate existence method calls to @result" do
|
73
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'bam' }
|
74
|
+
assert_respond_to result, :foo?
|
75
|
+
|
76
|
+
assert_equal true, result.foo?
|
77
|
+
assert_equal false, result.boo?
|
78
|
+
assert_equal false, result._source.foo?
|
79
|
+
assert_equal false, result._source.boo?
|
80
|
+
end
|
81
|
+
|
82
|
+
should "delegate as_json to @result even when ActiveSupport changed half of Ruby" do
|
83
|
+
require 'active_support/json/encoding'
|
84
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar'
|
85
|
+
|
86
|
+
result.instance_variable_get(:@result).expects(:as_json)
|
87
|
+
result.as_json(except: 'foo')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResultsTest < Test::Unit::TestCase
|
4
|
+
context "Response results" do
|
5
|
+
class OriginClass
|
6
|
+
def self.index_name; 'foo'; end
|
7
|
+
def self.document_type; 'bar'; end
|
8
|
+
end
|
9
|
+
|
10
|
+
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'foo' => 'bar'}] } }
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
|
14
|
+
@response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
15
|
+
@results = Elasticsearch::Model::Response::Results.new OriginClass, @response
|
16
|
+
@search.stubs(:execute!).returns(RESPONSE)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "access the results" do
|
20
|
+
assert_respond_to @results, :results
|
21
|
+
assert_equal 1, @results.results.size
|
22
|
+
assert_equal 'bar', @results.results.first.foo
|
23
|
+
end
|
24
|
+
|
25
|
+
should "delegate Enumerable methods to results" do
|
26
|
+
assert ! @results.empty?
|
27
|
+
assert_equal 'bar', @results.first.foo
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResponseTest < Test::Unit::TestCase
|
4
|
+
context "Response" do
|
5
|
+
class OriginClass
|
6
|
+
def self.index_name; 'foo'; end
|
7
|
+
def self.document_type; 'bar'; end
|
8
|
+
end
|
9
|
+
|
10
|
+
RESPONSE = { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'}, 'hits' => { 'hits' => [] } }
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
|
14
|
+
@search.stubs(:execute!).returns(RESPONSE)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "access klass, response, took, timed_out, shards" do
|
18
|
+
response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
19
|
+
|
20
|
+
assert_equal OriginClass, response.klass
|
21
|
+
assert_equal @search, response.search
|
22
|
+
assert_equal RESPONSE, response.response
|
23
|
+
assert_equal '5', response.took
|
24
|
+
assert_equal false, response.timed_out
|
25
|
+
assert_equal 'OK', response.shards.one
|
26
|
+
end
|
27
|
+
|
28
|
+
should "wrap the raw Hash response in Hashie::Mash" do
|
29
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
|
30
|
+
@search.stubs(:execute!).returns({'hits' => { 'hits' => [] }, 'aggregations' => { 'dates' => 'FOO' }})
|
31
|
+
|
32
|
+
response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
33
|
+
|
34
|
+
assert_respond_to response.response, :aggregations
|
35
|
+
assert_equal 'FOO', response.response.aggregations.dates
|
36
|
+
end
|
37
|
+
|
38
|
+
should "load and access the results" do
|
39
|
+
@search.expects(:execute!).returns(RESPONSE)
|
40
|
+
|
41
|
+
response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
42
|
+
assert_instance_of Elasticsearch::Model::Response::Results, response.results
|
43
|
+
assert_equal 0, response.size
|
44
|
+
end
|
45
|
+
|
46
|
+
should "load and access the records" do
|
47
|
+
@search.expects(:execute!).returns(RESPONSE)
|
48
|
+
|
49
|
+
response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
50
|
+
assert_instance_of Elasticsearch::Model::Response::Records, response.records
|
51
|
+
assert_equal 0, response.size
|
52
|
+
end
|
53
|
+
|
54
|
+
should "delegate Enumerable methods to results" do
|
55
|
+
@search.expects(:execute!).returns(RESPONSE)
|
56
|
+
|
57
|
+
response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
58
|
+
assert response.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
should "be initialized lazily" do
|
62
|
+
@search.expects(:execute!).never
|
63
|
+
|
64
|
+
Elasticsearch::Model::Response::Response.new OriginClass, @search
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::SearchRequestTest < Test::Unit::TestCase
|
4
|
+
context "SearchRequest class" do
|
5
|
+
class ::DummySearchingModel
|
6
|
+
extend Elasticsearch::Model::Searching::ClassMethods
|
7
|
+
|
8
|
+
def self.index_name; 'foo'; end
|
9
|
+
def self.document_type; 'bar'; end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
setup do
|
14
|
+
@client = mock('client')
|
15
|
+
DummySearchingModel.stubs(:client).returns(@client)
|
16
|
+
end
|
17
|
+
|
18
|
+
should "pass the search definition as a simple query" do
|
19
|
+
@client.expects(:search).with do |params|
|
20
|
+
assert_equal 'foo', params[:q]
|
21
|
+
true
|
22
|
+
end
|
23
|
+
.returns({})
|
24
|
+
|
25
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, 'foo'
|
26
|
+
s.execute!
|
27
|
+
end
|
28
|
+
|
29
|
+
should "pass the search definition as a Hash" do
|
30
|
+
@client.expects(:search).with do |params|
|
31
|
+
assert_equal( {foo: 'bar'}, params[:body] )
|
32
|
+
true
|
33
|
+
end
|
34
|
+
.returns({})
|
35
|
+
|
36
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, foo: 'bar'
|
37
|
+
s.execute!
|
38
|
+
end
|
39
|
+
|
40
|
+
should "pass the search definition as a JSON string" do
|
41
|
+
@client.expects(:search).with do |params|
|
42
|
+
assert_equal( '{"foo":"bar"}', params[:body] )
|
43
|
+
true
|
44
|
+
end
|
45
|
+
.returns({})
|
46
|
+
|
47
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, '{"foo":"bar"}'
|
48
|
+
s.execute!
|
49
|
+
end
|
50
|
+
|
51
|
+
should "pass the search definition as an object which responds to to_hash" do
|
52
|
+
class MySpecialQueryBuilder
|
53
|
+
def to_hash; {foo: 'bar'}; end
|
54
|
+
end
|
55
|
+
|
56
|
+
@client.expects(:search).with do |params|
|
57
|
+
assert_equal( {foo: 'bar'}, params[:body] )
|
58
|
+
true
|
59
|
+
end
|
60
|
+
.returns({})
|
61
|
+
|
62
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, MySpecialQueryBuilder.new
|
63
|
+
s.execute!
|
64
|
+
end
|
65
|
+
|
66
|
+
should "pass the options to the client" do
|
67
|
+
@client.expects(:search).with do |params|
|
68
|
+
assert_equal 'foo', params[:q]
|
69
|
+
assert_equal 15, params[:size]
|
70
|
+
true
|
71
|
+
end
|
72
|
+
.returns({})
|
73
|
+
|
74
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, 'foo', size: 15
|
75
|
+
s.execute!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::SearchingTest < Test::Unit::TestCase
|
4
|
+
context "Searching module" do
|
5
|
+
class ::DummySearchingModel
|
6
|
+
extend Elasticsearch::Model::Searching::ClassMethods
|
7
|
+
|
8
|
+
def self.index_name; 'foo'; end
|
9
|
+
def self.document_type; 'bar'; end
|
10
|
+
end
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@client = mock('client')
|
14
|
+
DummySearchingModel.stubs(:client).returns(@client)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "have the search method" do
|
18
|
+
assert_respond_to DummySearchingModel, :search
|
19
|
+
end
|
20
|
+
|
21
|
+
should "initialize the search object" do
|
22
|
+
Elasticsearch::Model::Searching::SearchRequest
|
23
|
+
.expects(:new).with do |klass, query, options|
|
24
|
+
assert_equal DummySearchingModel, klass
|
25
|
+
assert_equal 'foo', query
|
26
|
+
assert_equal({default_operator: 'AND'}, options)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
.returns( stub('search') )
|
30
|
+
|
31
|
+
DummySearchingModel.search 'foo', default_operator: 'AND'
|
32
|
+
end
|
33
|
+
|
34
|
+
should "not execute the search" do
|
35
|
+
Elasticsearch::Model::Searching::SearchRequest
|
36
|
+
.expects(:new).returns( mock('search').expects(:execute!).never )
|
37
|
+
|
38
|
+
DummySearchingModel.search 'foo'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::SerializingTest < Test::Unit::TestCase
|
4
|
+
context "Serializing module" do
|
5
|
+
class DummyClass
|
6
|
+
include Elasticsearch::Model::Serializing::InstanceMethods
|
7
|
+
|
8
|
+
def as_json(options={})
|
9
|
+
'HASH'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
should "delegate to as_json by default" do
|
14
|
+
assert_equal 'HASH', DummyClass.new.as_indexed_json
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|