elastic_mapper 0.0.1 → 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 +5 -13
- data/README.md +83 -17
- data/lib/elastic_mapper/search.rb +5 -1
- data/lib/elastic_mapper/version.rb +1 -1
- data/spec/elastic_mapper/search_spec.rb +18 -16
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YWE3YTVkZjZiNjRhMGNmNTY2ZjdmNDg1OWY4MWZlODI5Y2M4ZjhmNA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 44bac02c15e1ea5ac170e5ead716ed32d2a2e0c9
|
4
|
+
data.tar.gz: 1b1263a1980b20109be0a125776b56c597014066
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OGRjYzBkM2IxYjdiNDBkZDk0ZDNkNzM4NWI0YWY1MmVkMGY1NTU1YTNkMjg5
|
11
|
-
ZWY2NjBjMDVjZWI3OGExNmFhNDRiNmM0YWQ3ZGYxNTc1ODRmOGY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NzhlNWU0OWM5NDIyNTRhNmQ2YjliZmY2N2FjYjliOTA1ZDI5YmIwMThmYTM3
|
14
|
-
MmNmZWUyMzQ4OGM0OTNmOTdkOGRmOGVmMzY4MzgzYjE3ZWZkMzRmZDFlNGJh
|
15
|
-
N2YxODVkZGQ2NWZhMjc0MDVhZDJlY2Y0YzMxN2VkOTc2MWY3ZTQ=
|
6
|
+
metadata.gz: 7d034a538c4f0f657cddff452dbfe87e88db7e911dd5b52f9226f4706ec71b067ecb7cd035884fa1f4d7f72befa28193a8af30475a39fb2dac702ab665a7d5b5
|
7
|
+
data.tar.gz: 5dd79e2a9978c2ad677e4d85da8e05c6e3cca2add42df49cc8755d316e4a317fb755349f296d036a8ffb3b2ff9199be8805b4f5c3e57d9017d1c9034e2cc6f0f
|
data/README.md
CHANGED
@@ -1,15 +1,25 @@
|
|
1
1
|
ElasticMapper
|
2
2
|
=============
|
3
3
|
|
4
|
-
A
|
4
|
+
A damn simple mixin for integrating ActiveModel with ElasticSearch.
|
5
5
|
|
6
|
-
ElasticMapper is built on top of the [Stretcher](https://github.com/PoseBiz/stretcher)
|
6
|
+
ElasticMapper is built on top of the [Stretcher](https://github.com/PoseBiz/stretcher) client.
|
7
7
|
|
8
8
|
Background
|
9
9
|
----------
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
I'm a big fan of the [Stretcher](https://github.com/PoseBiz/stretcher) ElasticSearch client. It exposes an API that's: straightforward, elegant, and well documented. I tend to choose stretcher when pulling search into Rails projects.
|
12
|
+
|
13
|
+
A few projects in, I noticed that I was rewriting a lot of the same code for:
|
14
|
+
|
15
|
+
* describing the mappings on documents.
|
16
|
+
* indexing documents.
|
17
|
+
* and searching for documents.
|
18
|
+
|
19
|
+
From this grew ElasticMapper; Simply include the ElasticMapper mixin in your ActiveModels, it provides helpers for: generating mappings, indexing documents, and performing search.
|
20
|
+
|
21
|
+
Creating Mappings
|
22
|
+
-----------------
|
13
23
|
|
14
24
|
Mappings indicate to ElasticSearch how the fields of a document should be indexed:
|
15
25
|
|
@@ -18,32 +28,92 @@ http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping.ht
|
|
18
28
|
ElasticMapper provides a `mapping` method, for describing these mappings.
|
19
29
|
|
20
30
|
```ruby
|
21
|
-
def Article
|
31
|
+
def Article < ActiveHash::Base
|
22
32
|
include ElasticMapper
|
23
33
|
|
34
|
+
# Note we might sometimes want to index the same field in a few
|
35
|
+
# different ways, ElasticMapper creates a unique name automatically
|
36
|
+
# if fields collide :title, :title_1, ...
|
24
37
|
mapping :title, :doi, { type => :string, index => :not_analyzed }
|
25
38
|
mapping :title, :abstract, type => :string
|
26
39
|
mapping :publication_date, type => :date
|
27
40
|
end
|
28
41
|
```
|
29
42
|
|
30
|
-
When you
|
43
|
+
When you create or modify mappings on an ElasticMapper model, you should run:
|
31
44
|
|
32
45
|
```ruby
|
33
46
|
Article.put_mapping
|
34
47
|
```
|
35
48
|
|
36
|
-
|
37
|
-
|
49
|
+
Indexing a Document
|
50
|
+
-------------------
|
51
|
+
|
52
|
+
When you create or update a document using the ElasticMapper mixin, simply call `index`.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
article = Article.create(title: "Hello World", doi: "doi://12354.com")
|
56
|
+
article.index
|
57
|
+
```
|
58
|
+
|
59
|
+
Or, even easier, use the ActiveRecord `:after_save` hook:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class Article < ActiveRecord::Base
|
63
|
+
|
64
|
+
include ElasticMapper
|
65
|
+
|
66
|
+
validates_uniqueness_of :doi
|
67
|
+
validates_presence_of :doi, :title
|
68
|
+
|
69
|
+
after_save :index
|
70
|
+
|
71
|
+
mapping :title, :doi, :index => :not_analyzed
|
72
|
+
mapping :title, :abstract
|
73
|
+
mapping :publication_date, :type => :date
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
Searching
|
78
|
+
---------
|
79
|
+
|
80
|
+
ElasticMapper adds the `search` method to your ActiveModel classes. Results will be returned as instances of your ActiveModel class.
|
38
81
|
|
39
|
-
*
|
40
|
-
|
82
|
+
*String Queries*
|
83
|
+
|
84
|
+
You can provide a string query to your model, and it will be parsed using the ElasticSearch query DSL:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
articles = Article.search('hello AND world')
|
88
|
+
```
|
89
|
+
|
90
|
+
*Hash Queries*
|
91
|
+
|
92
|
+
You can also provide a hash object, for advanced searches.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
articles = Article.search({ "query_string" => { "query" => 'alpha' } })
|
96
|
+
```
|
97
|
+
|
98
|
+
*Pagination*
|
99
|
+
|
100
|
+
* `:size` how many search results should be returned?
|
101
|
+
* `:from` what offset should we start returning results from?
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
results = SearchModel.search('* OR alpha', size: 10, from: 10)
|
105
|
+
```
|
106
|
+
|
107
|
+
That's It
|
108
|
+
---------
|
109
|
+
|
110
|
+
Let me know what you think!
|
41
111
|
|
42
112
|
## Installation
|
43
113
|
|
44
114
|
Add this line to your application's Gemfile:
|
45
115
|
|
46
|
-
gem '
|
116
|
+
gem 'elastic_mapper'
|
47
117
|
|
48
118
|
And then execute:
|
49
119
|
|
@@ -51,15 +121,11 @@ And then execute:
|
|
51
121
|
|
52
122
|
Or install it yourself as:
|
53
123
|
|
54
|
-
$ gem install
|
55
|
-
|
56
|
-
## Usage
|
57
|
-
|
58
|
-
TODO: Write usage instructions here
|
124
|
+
$ gem install elastic_mapper
|
59
125
|
|
60
126
|
## Contributing
|
61
127
|
|
62
|
-
1. Fork it ( http://github.com
|
128
|
+
1. Fork it ( http://github.com/bcoe/elasticmapper/fork )
|
63
129
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
64
130
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
65
131
|
4. Push to the branch (`git push origin my-new-feature`)
|
@@ -55,7 +55,11 @@ module ElasticMapper::Search
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
Hashie::Mash.new({
|
59
|
+
documents: ordered_results(res.results.map(&:id)),
|
60
|
+
from: opts[:from],
|
61
|
+
total: res.total
|
62
|
+
})
|
59
63
|
end
|
60
64
|
|
61
65
|
# Create a query hash from a query string.
|
@@ -30,55 +30,57 @@ describe ElasticMapper::Search do
|
|
30
30
|
|
31
31
|
it "returns documents matching a query string" do
|
32
32
|
results = SearchModel.search('alpha')
|
33
|
-
results.count.should == 1
|
34
|
-
results.first.foo.should == 'alpha century'
|
33
|
+
results.documents.count.should == 1
|
34
|
+
results.documents.first.foo.should == 'alpha century'
|
35
35
|
end
|
36
36
|
|
37
37
|
it "supports elasticsearch query DSL" do
|
38
38
|
results = SearchModel.search('*')
|
39
|
-
results.count.should == 3
|
39
|
+
results.documents.count.should == 3
|
40
40
|
end
|
41
41
|
|
42
42
|
it "handles escaping invalid search string" do
|
43
43
|
results = SearchModel.search('AND AND mars')
|
44
|
-
results.count.should == 1
|
45
|
-
results.first.foo.should == 'alpha century'
|
44
|
+
results.documents.count.should == 1
|
45
|
+
results.documents.first.foo.should == 'alpha century'
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
context "search by hash" do
|
50
50
|
it "returns documents matching the hash query" do
|
51
51
|
results = SearchModel.search({ "query_string" => { "query" => 'alpha' } })
|
52
|
-
results.count.should == 1
|
53
|
-
results.first.foo.should == 'alpha century'
|
52
|
+
results.documents.count.should == 1
|
53
|
+
results.documents.first.foo.should == 'alpha century'
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
context "sort" do
|
58
58
|
it "can sort in descending order" do
|
59
59
|
results = SearchModel.search('*', sort: { :foo => :desc })
|
60
|
-
results.first.foo.should == 'hello world'
|
61
|
-
results.second.foo.should == 'cat lover'
|
60
|
+
results.documents.first.foo.should == 'hello world'
|
61
|
+
results.documents.second.foo.should == 'cat lover'
|
62
62
|
end
|
63
63
|
|
64
64
|
it "can sort in ascending order" do
|
65
65
|
results = SearchModel.search('*', sort: { :foo => :asc })
|
66
|
-
results.first.foo.should == 'alpha century'
|
67
|
-
results.second.foo.should == 'cat lover'
|
66
|
+
results.documents.first.foo.should == 'alpha century'
|
67
|
+
results.documents.second.foo.should == 'cat lover'
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
context "pagination" do
|
72
72
|
it "allows result size to be set with size" do
|
73
73
|
results = SearchModel.search('* OR alpha', size: 1)
|
74
|
-
results.count.should == 1
|
75
|
-
results.first.foo.should == 'alpha century'
|
74
|
+
results.documents.count.should == 1
|
75
|
+
results.documents.first.foo.should == 'alpha century'
|
76
76
|
end
|
77
77
|
|
78
78
|
it "allows documents to be skipped with from" do
|
79
|
-
results = SearchModel.search('* OR alpha', size: 1, from: 1)
|
80
|
-
results.
|
81
|
-
results.
|
79
|
+
results = SearchModel.search({ "query_string" => { "query" => '* OR alpha' } }, size: 1, from: 1)
|
80
|
+
results.total.should == 3
|
81
|
+
results.from.should == 1
|
82
|
+
results.documents.count.should == 1
|
83
|
+
results.documents.first.foo.should == 'hello world'
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Coe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: stretcher
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -42,70 +42,70 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: activesupport
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: active_hash
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description:
|
@@ -141,12 +141,12 @@ require_paths:
|
|
141
141
|
- lib
|
142
142
|
required_ruby_version: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- -
|
144
|
+
- - '>='
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
|
-
- -
|
149
|
+
- - '>='
|
150
150
|
- !ruby/object:Gem::Version
|
151
151
|
version: '0'
|
152
152
|
requirements: []
|