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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '01498d9fe5aeb06096b245b7045bc558d66edfb7'
4
- data.tar.gz: 659c1c312134ec3acba593feaa8ab1597d21611f
3
+ metadata.gz: 1184cc3821b5bee90dcb18d41ad3b6ea9a93b750
4
+ data.tar.gz: 11ac50692f0cfc629e4283baa588e20cba18d854
5
5
  SHA512:
6
- metadata.gz: a672c99130602f2461208d94f50e659d77f4e9b38b9b2149ed5e28665b1a5a3283fe6217a4322cdfba4af990849f09bd51fa2b9791f889bdea570458c3d86205
7
- data.tar.gz: a283066a539ead576d84dd83265f911d090fbc86b340a1f9b26d033305c5943fece67a7fbd51374c59c2ae86984752341ae39a2d551dee7fbbb29d814ceb1baa
6
+ metadata.gz: c0e51193c7b3d7989f973472e5cdc4335f3ed428fa73c56ddbefa271023c053c85107639fc6f05bf0dee00820e4eb729cea3782ab7f0d62cb197d3587e7da624
7
+ data.tar.gz: ab05d37fe0469216d05dff6fa0223dd7530832b0a945226352a67a270a2e5239376111418793b7ccff8c2245b68916d46cc71fcba486c8a3f9b48c96d9b30904
@@ -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 origin 4.0.1
11
- - git checkout ae43e164d4b09d7753e27bb7cba6f7f4f85326b3
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/src
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
@@ -2,10 +2,11 @@ source 'https://rubygems.org'
2
2
 
3
3
  ruby '2.4.1'
4
4
 
5
- gem 'redis', '~> 4.0.0.rc1'
5
+ gem 'redis', '~> 4.0.1'
6
6
 
7
7
  group :development, :test do
8
8
  gem 'dotenv'
9
+ gem 'rake'
9
10
  gem 'subprocess'
10
11
  gem 'minitest', '~> 5.0'
11
12
  end
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:
@@ -12,12 +12,13 @@ class RediSearch
12
12
  #
13
13
  # { verbatim: true, withscores: true, withsortkey: false }
14
14
 
15
- CREATE_OPTIONS_FLAGS = [:nooffsets, :nofreqs, :noscoreidx, :nofields]
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
- multi { docs.each { |doc_id, fields| @redis.call(ft_add(doc_id, fields, opts)) } }
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
- #@return [Array] documents matching the query
98
+ # @return [Array] documents matching the query
98
99
  def search(query, opts = {})
99
- results_to_hash(call(ft_search(query, opts)), opts)
100
+ build_docs(call(ft_search(query, opts)), opts)
100
101
  end
101
102
 
102
103
  # Fetch a document by id
103
- def get_by_id(id)
104
- Hash[with_reconnect { @redis.hgetall(id) } || []]
105
- .tap { |doc| doc['id'] = id unless doc.empty? }
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
- params_keys.map do |key|
170
- [key.to_s.upcase, *opts[key]] unless opts[key].nil?
171
- end.compact
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 results_to_hash(results, opts = {})
220
+ def build_docs(results, opts = {})
175
221
  return {} if results.nil? || results[0] == 0
176
222
  results.shift
177
- offset = opts[:withscores] ? 1 : 0
178
- rows_per_doc = 2 + offset
179
- nr_of_docs = results.size / (2 + offset)
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 + 1 + offset]]
182
- doc['score'] = results[rows_per_doc * n + offset] if offset > 0
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
@@ -1,3 +1,3 @@
1
1
  class RediSearch
2
- VERSION = '0.1.8'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -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
@@ -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.1.8
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: 2017-09-16 00:00:00.000000000 Z
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: '0'
48
+ version: 2.4.0
49
49
  required_rubygems_version: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="