redisearch-rb 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -4
- data/Gemfile +2 -1
- data/README.md +2 -2
- data/lib/redisearch.rb +74 -23
- data/lib/redisearch/version.rb +1 -1
- data/redisearch-rb.gemspec +1 -1
- data/test/redisearch_test.rb +15 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1184cc3821b5bee90dcb18d41ad3b6ea9a93b750
|
4
|
+
data.tar.gz: 11ac50692f0cfc629e4283baa588e20cba18d854
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0e51193c7b3d7989f973472e5cdc4335f3ed428fa73c56ddbefa271023c053c85107639fc6f05bf0dee00820e4eb729cea3782ab7f0d62cb197d3587e7da624
|
7
|
+
data.tar.gz: ab05d37fe0469216d05dff6fa0223dd7530832b0a945226352a67a270a2e5239376111418793b7ccff8c2245b68916d46cc71fcba486c8a3f9b48c96d9b30904
|
data/.travis.yml
CHANGED
@@ -7,12 +7,14 @@ before_install:
|
|
7
7
|
- gem install bundler -v 1.14.6
|
8
8
|
- git clone --depth 10 https://github.com/antirez/redis.git
|
9
9
|
- cd redis
|
10
|
-
- git fetch
|
11
|
-
- git checkout
|
10
|
+
- git fetch && git fetch --tags
|
11
|
+
- git checkout 4.0.6
|
12
12
|
- make
|
13
13
|
- cd ..
|
14
14
|
- git clone --depth 1 https://github.com/RedisLabsModules/RediSearch.git
|
15
|
-
- cd RediSearch
|
15
|
+
- cd RediSearch
|
16
|
+
- git fetch && git fetch --tags
|
17
|
+
- git checkout v1.0.4
|
16
18
|
- make all
|
17
|
-
- ls -la *.so
|
18
19
|
- cd ..
|
20
|
+
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -10,8 +10,8 @@ http://redisearch.io/
|
|
10
10
|
|
11
11
|
First of all, you need to install RediSearch, if you haven't yet:
|
12
12
|
|
13
|
-
1. Install Redis 4.0.1 https://github.com/antirez/redis/releases/tag/4.0.1
|
14
|
-
2. Install RediSearch http://redisearch.io/Quick_Start/
|
13
|
+
1. Install Redis 4.0.1 or highger https://github.com/antirez/redis/releases/tag/4.0.1
|
14
|
+
2. Install RediSearch 1.0.4 or higher http://redisearch.io/Quick_Start/
|
15
15
|
3. Edit your `redis.conf` file and add a `loadmodule` directive to load the RediSearch module built in the step 2.
|
16
16
|
|
17
17
|
To install this gem, add this line to your application's Gemfile:
|
data/lib/redisearch.rb
CHANGED
@@ -12,12 +12,13 @@ class RediSearch
|
|
12
12
|
#
|
13
13
|
# { verbatim: true, withscores: true, withsortkey: false }
|
14
14
|
|
15
|
-
CREATE_OPTIONS_FLAGS = [:nooffsets, :nofreqs, :
|
16
|
-
ADD_OPTIONS_FLAGS = [:nosave, :replace]
|
15
|
+
CREATE_OPTIONS_FLAGS = [:nooffsets, :nofreqs, :nohl, :nofields]
|
16
|
+
ADD_OPTIONS_FLAGS = [:nosave, :replace, :partial]
|
17
17
|
SEARCH_OPTIONS_FLAGS = [:nocontent, :verbatim, :nostopwords, :withscores, :withsortkeys]
|
18
18
|
|
19
19
|
# Params options need an array with the values for the option
|
20
20
|
# { limit: ['0', '50'], sortby: ['year', 'desc'], return: ['2', 'title', 'year'] }
|
21
|
+
CREATE_OPTIONS_PARAMS = [:stopwords]
|
21
22
|
ADD_OPTIONS_PARAMS = [:language]
|
22
23
|
SEARCH_OPTIONS_PARAMS = [:filter, :return, :infields, :inkeys, :slop, :scorer, :sortby, :limit]
|
23
24
|
|
@@ -36,11 +37,11 @@ class RediSearch
|
|
36
37
|
|
37
38
|
# Create new index with the given `schema`
|
38
39
|
# @param [Array] schema
|
39
|
-
#
|
40
|
+
# @param [Hash] opts options
|
40
41
|
# Example:
|
41
42
|
#
|
42
43
|
# redisearch = RediSearch.new('my_idx')
|
43
|
-
# redisearch.create_idx(['title', 'TEXT', 'WEIGHT', '2.0', 'director', 'TEXT', 'WEIGHT', '1.0'])
|
44
|
+
# redisearch.create_idx(['title', 'TEXT', 'WEIGHT', '2.0', 'director', 'TEXT', 'WEIGHT', '1.0', 'year', 'NUMERIC', 'SORTABLE'])
|
44
45
|
#
|
45
46
|
# See http://redisearch.io/Commands/#ftcreate
|
46
47
|
#
|
@@ -87,22 +88,25 @@ class RediSearch
|
|
87
88
|
# See http://redisearch.io/Commands/#ftadd
|
88
89
|
# @return [String] "OK" on success
|
89
90
|
def add_docs(docs, opts = {})
|
90
|
-
|
91
|
+
docs.each { |doc_id, fields| call(ft_add(doc_id, fields, opts))}
|
91
92
|
end
|
92
93
|
|
93
94
|
# Search the index with the given `query`
|
94
95
|
# @param [String] query text query, see syntax here http://redisearch.io/Query_Syntax/
|
95
96
|
# @param [Hash] opts options for the query
|
96
97
|
#
|
97
|
-
|
98
|
+
# @return [Array] documents matching the query
|
98
99
|
def search(query, opts = {})
|
99
|
-
|
100
|
+
build_docs(call(ft_search(query, opts)), opts)
|
100
101
|
end
|
101
102
|
|
102
103
|
# Fetch a document by id
|
103
|
-
|
104
|
-
|
105
|
-
|
104
|
+
#
|
105
|
+
# @param [String] doc_id id assigned to the document
|
106
|
+
# @return [Hash] Hash containing document
|
107
|
+
def get_by_id(doc_id)
|
108
|
+
Hash[*call(ft_get(doc_id))]
|
109
|
+
.tap { |doc| doc['id'] = doc_id unless doc.empty? } || {}
|
106
110
|
end
|
107
111
|
|
108
112
|
# Return information and statistics on the index.
|
@@ -112,6 +116,36 @@ class RediSearch
|
|
112
116
|
Hash[*call(ft_info)]
|
113
117
|
end
|
114
118
|
|
119
|
+
# Deletes a document from the index
|
120
|
+
#
|
121
|
+
# See http://redisearch.io/Commands/#ftdel
|
122
|
+
#
|
123
|
+
# @param [String] doc_id id assigned to the document
|
124
|
+
# @return [int] 1 if the document was in the index, or 0 if not.
|
125
|
+
def delete_by_id(doc_id)
|
126
|
+
call(ft_del(doc_id))
|
127
|
+
end
|
128
|
+
|
129
|
+
# Deletes all documents returned by the query
|
130
|
+
#
|
131
|
+
# @param [String] query in the same format as used in `search`
|
132
|
+
# @param [Hash] opts options for the query, same as in `search`
|
133
|
+
# @return [int] count of documents deleted
|
134
|
+
def delete_by_query(query, opts = {})
|
135
|
+
call(ft_search(query, opts.merge(nocontent: true)))[1..-1].map do |doc_id|
|
136
|
+
call(ft_del(doc_id))
|
137
|
+
end.sum
|
138
|
+
end
|
139
|
+
|
140
|
+
# Execute arbitrary command. Only RediSearch commands are allowed
|
141
|
+
#
|
142
|
+
# @param [Array] command
|
143
|
+
# @return [mixed] The output returned by redis
|
144
|
+
def call(command)
|
145
|
+
raise ArgumentError.new("#{command&.first} is not a RediSearch command") unless valid_command?(command)
|
146
|
+
@redis.with_reconnect { @redis.call(command.flatten) }
|
147
|
+
end
|
148
|
+
|
115
149
|
private
|
116
150
|
|
117
151
|
def with_reconnect
|
@@ -122,10 +156,6 @@ class RediSearch
|
|
122
156
|
@redis.with_reconnect { @redis.multi { yield } }
|
123
157
|
end
|
124
158
|
|
125
|
-
def call(command)
|
126
|
-
@redis.with_reconnect { @redis.call(command) }
|
127
|
-
end
|
128
|
-
|
129
159
|
def add(doc_id, fields)
|
130
160
|
@redis.call(ft_add(doc_id, fields))
|
131
161
|
end
|
@@ -146,10 +176,26 @@ class RediSearch
|
|
146
176
|
['FT.ADD', @idx_name , doc_id, weight || DEFAULT_WEIGHT, *add_options(opts), 'FIELDS', *fields]
|
147
177
|
end
|
148
178
|
|
179
|
+
def ft_add_hash(doc_id, opts = {}, weight = nil)
|
180
|
+
['FT.ADDHASH', @idx_name , doc_id, weight || DEFAULT_WEIGHT, *add_options(opts)]
|
181
|
+
end
|
182
|
+
|
149
183
|
def ft_search(query, opts)
|
150
184
|
['FT.SEARCH', @idx_name, *query, *search_options(opts)].flatten
|
151
185
|
end
|
152
186
|
|
187
|
+
def ft_get(doc_id)
|
188
|
+
['FT.GET', @idx_name , doc_id]
|
189
|
+
end
|
190
|
+
|
191
|
+
def ft_mget(doc_ids)
|
192
|
+
['FT.MGET', @idx_name , *doc_ids]
|
193
|
+
end
|
194
|
+
|
195
|
+
def ft_del(doc_id)
|
196
|
+
['FT.DEL', @idx_name , doc_id]
|
197
|
+
end
|
198
|
+
|
153
199
|
def create_options(opts = {})
|
154
200
|
build_options(opts, CREATE_OPTIONS_FLAGS, [])
|
155
201
|
end
|
@@ -166,22 +212,27 @@ class RediSearch
|
|
166
212
|
flags_keys.map do |key|
|
167
213
|
key.to_s.upcase if opts[key]
|
168
214
|
end.compact +
|
169
|
-
|
170
|
-
|
171
|
-
|
215
|
+
params_keys.map do |key|
|
216
|
+
[key.to_s.upcase, *opts[key]] unless opts[key].nil?
|
217
|
+
end.compact
|
172
218
|
end
|
173
219
|
|
174
|
-
def
|
220
|
+
def build_docs(results, opts = {})
|
175
221
|
return {} if results.nil? || results[0] == 0
|
176
222
|
results.shift
|
177
|
-
|
178
|
-
|
179
|
-
|
223
|
+
score_offset = opts[:withscores] ? 1 : 0
|
224
|
+
content_offset = score_offset + 1
|
225
|
+
rows_per_doc = 1 + content_offset
|
226
|
+
nr_of_docs = results.size / rows_per_doc
|
180
227
|
(0..nr_of_docs-1).map do |n|
|
181
|
-
doc = Hash[*results[rows_per_doc * n +
|
182
|
-
doc['score'] = results[rows_per_doc * n +
|
228
|
+
doc = opts[:nocontent] ? {} : Hash[*results[rows_per_doc * n + content_offset]]
|
229
|
+
doc['score'] = results[rows_per_doc * n + score_offset] if opts[:withscores]
|
183
230
|
doc['id'] = results[rows_per_doc * n]
|
184
231
|
doc
|
185
232
|
end
|
186
233
|
end
|
234
|
+
|
235
|
+
def valid_command?(command)
|
236
|
+
command[0] =~ /^ft\./i
|
237
|
+
end
|
187
238
|
end
|
data/lib/redisearch/version.rb
CHANGED
data/redisearch-rb.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
RediSearch is a Redis powered search engine, developed by RedisLabs. http://redisearch.io/"
|
13
13
|
spec.homepage = "https://github.com/vruizext/redisearch-rb"
|
14
14
|
spec.license = "MIT"
|
15
|
-
|
15
|
+
spec.required_ruby_version = '> 2.4.0'
|
16
16
|
spec.files = `git ls-files`.split("\n")
|
17
17
|
spec.test_files = `git ls-files -- {test}/*`.split("\n")
|
18
18
|
end
|
data/test/redisearch_test.rb
CHANGED
@@ -10,6 +10,7 @@ class RediSearchTest < Minitest::Test
|
|
10
10
|
@redisearch_client = RediSearch.new('test_idx', @redis_client)
|
11
11
|
@schema = ['title', 'TEXT', 'WEIGHT', '2.0',
|
12
12
|
'director', 'TEXT', 'WEIGHT', '1.0',
|
13
|
+
'genre', 'TAG',
|
13
14
|
'year', 'NUMERIC', 'SORTABLE']
|
14
15
|
|
15
16
|
end
|
@@ -166,4 +167,18 @@ class RediSearchTest < Minitest::Test
|
|
166
167
|
assert_equal 1, info['max_doc_id'].to_i
|
167
168
|
assert_equal 5, info['num_terms'].to_i
|
168
169
|
end
|
170
|
+
|
171
|
+
def test_delete_by_id
|
172
|
+
assert(@redisearch_client.create_index(@schema))
|
173
|
+
docs = [['id_1', ['title', 'Lost in translation', 'director', 'Sofia Coppola', 'year', '2004']],
|
174
|
+
['id_2', ['title', 'Ex Machina', 'director', 'Alex Garland', 'year', '2014']],
|
175
|
+
['id_3', ['title', 'Terminator', 'director', 'James Cameron', 'year', '1984']],
|
176
|
+
['id_4', ['title', 'Blade Runner', 'director', 'Ridley Scott', 'year', '1982']]]
|
177
|
+
assert(@redisearch_client.add_docs(docs))
|
178
|
+
assert_equal(1, @redisearch_client.delete_by_id('id_1'))
|
179
|
+
assert_empty(@redisearch_client.search('@title:lost'))
|
180
|
+
assert(@redisearch_client.get_by_id('id_1').any?)
|
181
|
+
assert(@redis_client.del('id_1'))
|
182
|
+
assert(@redisearch_client.get_by_id('id_1').empty?)
|
183
|
+
end
|
169
184
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redisearch-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
A simple Ruby client library for RediSearch.
|
@@ -43,9 +43,9 @@ require_paths:
|
|
43
43
|
- lib
|
44
44
|
required_ruby_version: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 2.4.0
|
49
49
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - ">="
|