elasticsearch-model-queryable 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|