redi_search 5.0.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +3 -3
- data/.github/workflows/tests.yml +8 -5
- data/Gemfile +1 -0
- data/README.md +57 -58
- data/bin/console +8 -4
- data/bin/publish +2 -2
- data/gemfiles/activerecord_60.gemfile +1 -0
- data/gemfiles/activerecord_61.gemfile +1 -0
- data/gemfiles/activerecord_70.gemfile +2 -1
- data/lib/redi_search/add_field.rb +9 -15
- data/lib/redi_search/client.rb +9 -7
- data/lib/redi_search/document.rb +6 -11
- data/lib/redi_search/index.rb +4 -11
- data/lib/redi_search/model.rb +20 -28
- data/lib/redi_search/schema/field.rb +15 -1
- data/lib/redi_search/schema/geo_field.rb +5 -6
- data/lib/redi_search/schema/numeric_field.rb +5 -6
- data/lib/redi_search/schema/tag_field.rb +12 -8
- data/lib/redi_search/schema/text_field.rb +7 -6
- data/lib/redi_search/schema.rb +33 -25
- data/lib/redi_search/search/clauses/and.rb +0 -2
- data/lib/redi_search/search/clauses/application_clause.rb +0 -2
- data/lib/redi_search/search/clauses/boolean.rb +1 -1
- data/lib/redi_search/search/clauses/in_order.rb +0 -2
- data/lib/redi_search/search/clauses/language.rb +0 -2
- data/lib/redi_search/search/clauses/limit.rb +0 -2
- data/lib/redi_search/search/clauses/no_content.rb +0 -2
- data/lib/redi_search/search/clauses/no_stop_words.rb +0 -2
- data/lib/redi_search/search/clauses/or.rb +0 -2
- data/lib/redi_search/search/clauses/return.rb +0 -2
- data/lib/redi_search/search/clauses/slop.rb +0 -2
- data/lib/redi_search/search/clauses/sort_by.rb +0 -2
- data/lib/redi_search/search/clauses/verbatim.rb +0 -2
- data/lib/redi_search/search/clauses/where.rb +1 -1
- data/lib/redi_search/search/clauses/with_scores.rb +0 -2
- data/lib/redi_search/search/clauses.rb +0 -16
- data/lib/redi_search/search/term.rb +16 -9
- data/lib/redi_search/search.rb +0 -6
- data/lib/redi_search/spellcheck.rb +2 -6
- data/lib/redi_search/validatable.rb +0 -4
- data/lib/redi_search/validations/numericality.rb +0 -2
- data/lib/redi_search/version.rb +1 -1
- data/lib/redi_search.rb +3 -7
- data/redi_search.gemspec +8 -5
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44546188ac7648ecd413eea9c79c93fc76c23009476f585a2bf600e2da4afe3b
|
4
|
+
data.tar.gz: eb8b6db657a5f671a8d0da0f69653d97301f8c2d116cfc9427b5105133312495
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adda3ec25f90ea2a4b372549c1d1903a48774b890c9fd589e43ef87c7bccb11f19282f0e5b34df46026c7fffd4e3826ec4d6ef9d1a0216100846f5ece6f1bab7
|
7
|
+
data.tar.gz: a1dc85af4e881b0ad63ae54f4b36cbaead28f2558fdf48674d82ef996bd7bc4482f417c92df920ca4480a20ad05fc190c14300c45467b35c91db23b296fa6d0e
|
data/.github/workflows/lint.yml
CHANGED
@@ -4,17 +4,17 @@ on:
|
|
4
4
|
pull_request:
|
5
5
|
push:
|
6
6
|
branches:
|
7
|
-
-
|
7
|
+
- main
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
lint:
|
11
11
|
runs-on: ubuntu-latest
|
12
12
|
steps:
|
13
13
|
- uses: actions/checkout@v2
|
14
|
-
- name: Set up Ruby 3.
|
14
|
+
- name: Set up Ruby 3.1
|
15
15
|
uses: ruby/setup-ruby@v1
|
16
16
|
with:
|
17
|
-
ruby-version: 3.
|
17
|
+
ruby-version: 3.1
|
18
18
|
- name: Install rubocop
|
19
19
|
run: |
|
20
20
|
gem install rubocop rubocop-performance rubocop-minitest rubocop-rake
|
data/.github/workflows/tests.yml
CHANGED
@@ -4,14 +4,14 @@ on:
|
|
4
4
|
pull_request:
|
5
5
|
push:
|
6
6
|
branches:
|
7
|
-
-
|
7
|
+
- main
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
unit:
|
11
11
|
runs-on: ubuntu-latest
|
12
12
|
strategy:
|
13
13
|
matrix:
|
14
|
-
ruby: [ '2.7', '3.0' ]
|
14
|
+
ruby: [ '2.7', '3.0', '3.1' ]
|
15
15
|
gemfile: [ 'Gemfile', 'gemfiles/activerecord_60.gemfile', 'gemfiles/activerecord_61.gemfile', 'gemfiles/activerecord_70.gemfile' ]
|
16
16
|
steps:
|
17
17
|
- uses: actions/checkout@v2
|
@@ -29,17 +29,20 @@ jobs:
|
|
29
29
|
run: BUNDLE_GEMFILE=${{ matrix.gemfile }} bundle exec rake test:unit
|
30
30
|
integration:
|
31
31
|
runs-on: ubuntu-latest
|
32
|
+
strategy:
|
33
|
+
matrix:
|
34
|
+
redisearch: [ '2.0.14', '2.2.7' ]
|
32
35
|
services:
|
33
36
|
redisearch:
|
34
|
-
image: redislabs/redisearch
|
37
|
+
image: redislabs/redisearch:${{ matrix.redisearch }}
|
35
38
|
ports:
|
36
39
|
- 6379:6379
|
37
40
|
steps:
|
38
41
|
- uses: actions/checkout@v2
|
39
|
-
- name: Set up Ruby 3.
|
42
|
+
- name: Set up Ruby 3.1
|
40
43
|
uses: ruby/setup-ruby@v1
|
41
44
|
with:
|
42
|
-
ruby-version: 3.
|
45
|
+
ruby-version: 3.1
|
43
46
|
- name: Install dependencies
|
44
47
|
run: |
|
45
48
|
sudo apt-get install libsqlite3-dev -y
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<a href="https://github.com/npezza93/redi_search">
|
3
|
-
<img src="https://raw.githubusercontent.com/npezza93/redi_search/
|
3
|
+
<img src="https://raw.githubusercontent.com/npezza93/redi_search/main/.github/logo.svg?sanitize=true" width="350">
|
4
4
|
</a>
|
5
5
|
</p>
|
6
6
|
|
@@ -103,17 +103,19 @@ defining what a search index is. According to [Swiftype](https://swiftype.com):
|
|
103
103
|
## Schema
|
104
104
|
|
105
105
|
This defines the fields and the properties of those fields in the index. A
|
106
|
-
schema is a
|
107
|
-
|
108
|
-
and can have many options. A simple example of a schema is:
|
106
|
+
schema is a simple DSL. Each field can be one of four types: geo, numeric, tag,
|
107
|
+
or text and can have many options. A simple example of a schema is:
|
109
108
|
```ruby
|
110
|
-
|
109
|
+
RediSearch::Schema.new do
|
110
|
+
text_field :first_name
|
111
|
+
text_field :last_name
|
112
|
+
end
|
111
113
|
```
|
112
114
|
|
113
115
|
The supported options for each type are as follows:
|
114
116
|
|
115
117
|
##### Text field
|
116
|
-
With no options: `
|
118
|
+
With no options: `text_field :name`
|
117
119
|
|
118
120
|
<details>
|
119
121
|
<summary>Options</summary>
|
@@ -122,7 +124,7 @@ With no options: `{ name: :text }`
|
|
122
124
|
<b>weight</b> (default: 1.0)
|
123
125
|
<ul>
|
124
126
|
<li>Declares the importance of this field when calculating result accuracy. This is a multiplication factor.</li>
|
125
|
-
<li>Ex: <code>
|
127
|
+
<li>Ex: <code>text_field :name, weight: 2</code></li>
|
126
128
|
</ul>
|
127
129
|
</li>
|
128
130
|
<li>
|
@@ -137,7 +139,7 @@ With no options: `{ name: :text }`
|
|
137
139
|
</ul>
|
138
140
|
</li>
|
139
141
|
<li>
|
140
|
-
Ex: <code>
|
142
|
+
Ex: <code>text_field :name, phonetic: 'dm:en'</code>
|
141
143
|
</li>
|
142
144
|
</ul>
|
143
145
|
</li>
|
@@ -145,28 +147,28 @@ With no options: `{ name: :text }`
|
|
145
147
|
<b>sortable</b> (default: false)
|
146
148
|
<ul>
|
147
149
|
<li>Allows the user to later sort the results by the value of this field (this adds memory overhead so do not declare it on large text fields).</li>
|
148
|
-
<li>Ex: <code>
|
150
|
+
<li>Ex: <code>text_field :name, sortable: true</code></li>
|
149
151
|
</ul>
|
150
152
|
</li>
|
151
153
|
<li>
|
152
154
|
<b>no_index</b> (default: false)
|
153
155
|
<ul>
|
154
156
|
<li>Field will not be indexed. This is useful in conjunction with <code>sortable</code>, to create fields whose update using PARTIAL will not cause full reindexing of the document. If a field has <code>no_index</code> and doesn't have <code>sortable</code>, it will just be ignored by the index.</li>
|
155
|
-
<li>Ex: <code>
|
157
|
+
<li>Ex: <code>text_field :name, no_index: true</code></li>
|
156
158
|
</ul>
|
157
159
|
</li>
|
158
160
|
<li>
|
159
161
|
<b>no_stem</b> (default: false)
|
160
162
|
<ul>
|
161
163
|
<li>Disable stemming when indexing its values. This may be ideal for things like proper names.</li>
|
162
|
-
<li>Ex: <code>
|
164
|
+
<li>Ex: <code>text_feidl :name, no_stem: true</code></li>
|
163
165
|
</ul>
|
164
166
|
</li>
|
165
167
|
</ul>
|
166
168
|
</details>
|
167
169
|
|
168
170
|
##### Numeric field
|
169
|
-
With no options: `
|
171
|
+
With no options: `numeric_field :price`
|
170
172
|
|
171
173
|
<details>
|
172
174
|
<summary>Options</summary>
|
@@ -175,21 +177,21 @@ With no options: `{ price: :numeric }`
|
|
175
177
|
<b>sortable</b> (default: false)
|
176
178
|
<ul>
|
177
179
|
<li>Allows the user to later sort the results by the value of this field (this adds memory overhead so do not declare it on large text fields).</li>
|
178
|
-
<li>Ex: <code>
|
180
|
+
<li>Ex: <code>numeric_field :id, sortable: true</code></li>
|
179
181
|
</ul>
|
180
182
|
</li>
|
181
183
|
<li>
|
182
184
|
<b>no_index</b> (default: false)
|
183
185
|
<ul>
|
184
186
|
<li>Field will not be indexed. This is useful in conjunction with <code>sortable</code>, to create fields whose update using PARTIAL will not cause full reindexing of the document. If a field has <code>no_index</code> and doesn't have <code>sortable</code>, it will just be ignored by the index.</li>
|
185
|
-
<li>Ex: <code>
|
187
|
+
<li>Ex: <code>numeric_field :id, no_index: true</code></li>
|
186
188
|
</ul>
|
187
189
|
</li>
|
188
190
|
</ul>
|
189
191
|
</details>
|
190
192
|
|
191
193
|
##### Tag field
|
192
|
-
With no options: `
|
194
|
+
With no options: `tag_field :tag`
|
193
195
|
|
194
196
|
<details>
|
195
197
|
<summary>Options</summary>
|
@@ -198,28 +200,28 @@ With no options: `{ tag: :tag }`
|
|
198
200
|
<b>sortable</b> (default: false)
|
199
201
|
<ul>
|
200
202
|
<li>Allows the user to later sort the results by the value of this field (this adds memory overhead so do not declare it on large text fields).</li>
|
201
|
-
<li>Ex: <code>
|
203
|
+
<li>Ex: <code>tag_field :tag, sortable: true</code></li>
|
202
204
|
</ul>
|
203
205
|
</li>
|
204
206
|
<li>
|
205
207
|
<b>no_index</b> (default: false)
|
206
208
|
<ul>
|
207
209
|
<li>Field will not be indexed. This is useful in conjunction with <code>sortable</code>, to create fields whose update using PARTIAL will not cause full reindexing of the document. If a field has <code>no_index</code> and doesn't have <code>sortable</code>, it will just be ignored by the index.</li>
|
208
|
-
<li>Ex: <code>
|
210
|
+
<li>Ex: <code>tag_field :tag, no_index: true</code></li>
|
209
211
|
</ul>
|
210
212
|
</li>
|
211
213
|
<li>
|
212
214
|
<b>separator</b> (default: ",")
|
213
215
|
<ul>
|
214
216
|
<li>Indicates how the text contained in the field is to be split into individual tags. The default is ,. The value must be a single character.</li>
|
215
|
-
<li>Ex: <code>
|
217
|
+
<li>Ex: <code>tag_field :tag, separator: ','</code></li>
|
216
218
|
</ul>
|
217
219
|
</li>
|
218
220
|
</ul>
|
219
221
|
</details>
|
220
222
|
|
221
223
|
##### Geo field
|
222
|
-
With no options: `
|
224
|
+
With no options: `geo_field :place`
|
223
225
|
|
224
226
|
<details>
|
225
227
|
<summary>Options</summary>
|
@@ -228,14 +230,14 @@ With no options: `{ place: :geo }`
|
|
228
230
|
<b>sortable</b> (default: false)
|
229
231
|
<ul>
|
230
232
|
<li>Allows the user to later sort the results by the value of this field (this adds memory overhead so do not declare it on large text fields).</li>
|
231
|
-
<li>Ex: <code>
|
233
|
+
<li>Ex: <code>geo_field :place, sortable: true</code></li>
|
232
234
|
</ul>
|
233
235
|
</li>
|
234
236
|
<li>
|
235
237
|
<b>no_index</b> (default: false)
|
236
238
|
<ul>
|
237
239
|
<li>Field will not be indexed. This is useful in conjunction with <code>sortable</code>, to create fields whose update using PARTIAL will not cause full reindexing of the document. If a field has <code>no_index</code> and doesn't have <code>sortable</code>, it will just be ignored by the index.</li>
|
238
|
-
<li>Ex: <code>
|
240
|
+
<li>Ex: <code>geo_field :place, no_index: true</code></li>
|
239
241
|
</ul>
|
240
242
|
</li>
|
241
243
|
</ul>
|
@@ -250,12 +252,10 @@ You can fetch a `Document` using `.get` class methods.
|
|
250
252
|
given `document_id`.
|
251
253
|
|
252
254
|
You can also make a `Document` instance using the
|
253
|
-
`.for_object(index, record,
|
255
|
+
`.for_object(index, record, only: [])` class method. It takes
|
254
256
|
an `Index` instance and a Ruby object. That object must respond to all the
|
255
|
-
fields specified in the `Index`'s `Schema`
|
256
|
-
|
257
|
-
`Schema`. `only` accepts an array of fields from the schema and limits the
|
258
|
-
fields that are passed to the `Document`.
|
257
|
+
fields specified in the `Index`'s `Schema`. `only` accepts an array of fields
|
258
|
+
from the schema and limits the fields that are passed to the `Document`.
|
259
259
|
|
260
260
|
Once you have an instance of a `Document`, it responds to all the fields
|
261
261
|
specified in the `Index`'s `Schema` as methods and `document_id`. `document_id`
|
@@ -271,10 +271,12 @@ Finally there is a `#del` method that will remove the `Document` from the
|
|
271
271
|
## Index
|
272
272
|
|
273
273
|
To initialize an `Index`, pass the name of the `Index` as a string or symbol
|
274
|
-
and the `Schema
|
274
|
+
and the `Schema` block.
|
275
275
|
|
276
276
|
```ruby
|
277
|
-
RediSearch::Index.new(name_of_index
|
277
|
+
RediSearch::Index.new(name_of_index) do
|
278
|
+
text_field :foobar
|
279
|
+
end
|
278
280
|
```
|
279
281
|
|
280
282
|
#### Available Commands
|
@@ -330,8 +332,10 @@ RediSearch::Index.new(name_of_index, schema)
|
|
330
332
|
- Removes a `Document` from the `Index`.
|
331
333
|
- `document_count`
|
332
334
|
- Returns the number of `Document`s in the `Index`
|
333
|
-
- `add_field(
|
334
|
-
- Adds a new field to the `Index`.
|
335
|
+
- `add_field(name, type, **options, &block)`
|
336
|
+
- Adds a new field to the `Index`.
|
337
|
+
- The block and options are optional.
|
338
|
+
- Ex: `index.add_field(:first_name, :text, phonetic: "dm:en")`
|
335
339
|
- `reindex(documents, recreate: false)`
|
336
340
|
- If `recreate` is `true` the `Index` will be dropped and recreated
|
337
341
|
|
@@ -343,7 +347,7 @@ be chained together. When searching, an array of `Document`s is returned
|
|
343
347
|
which has public reader methods for all the schema fields.
|
344
348
|
|
345
349
|
```ruby
|
346
|
-
main ❯ index = RediSearch::Index.new("user_idx"
|
350
|
+
main ❯ index = RediSearch::Index.new("user_idx") { text_field :name, phonetic: "dm:en" }
|
347
351
|
main ❯ index.add RediSearch::Document.for_object(index, User.new("10039", "Gene", "Volkman"))
|
348
352
|
main ❯ index.add RediSearch::Document.for_object(index, User.new("9998", "Jeannie", "Ledner"))
|
349
353
|
main ❯ index.search("john")
|
@@ -473,7 +477,7 @@ returns an array where each element contains suggestions for each search term
|
|
473
477
|
and a normalized score based on its occurrences in the index.
|
474
478
|
|
475
479
|
```ruby
|
476
|
-
main ❯ index = RediSearch::Index.new("user_idx"
|
480
|
+
main ❯ index = RediSearch::Index.new("user_idx") { text_field :name, phonetic: "dm:en" }
|
477
481
|
main ❯ index.spellcheck("jimy")
|
478
482
|
RediSearch (1.1ms) FT.SPELLCHECK user_idx jimy DISTANCE 1
|
479
483
|
=> [#<RediSearch::Spellcheck::Result:0x00007f805591c670
|
@@ -495,10 +499,10 @@ keyword argument from inside your model. Ex:
|
|
495
499
|
|
496
500
|
```ruby
|
497
501
|
class User < ApplicationRecord
|
498
|
-
redi_search
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
+
redi_search do
|
503
|
+
text_field :first, phonetic: "dm:en"
|
504
|
+
text_field :last, phonetic: "dm:en"
|
505
|
+
end
|
502
506
|
end
|
503
507
|
```
|
504
508
|
|
@@ -515,21 +519,16 @@ similarly to `RediSearch::Index#reindex`. Some of the differences include:
|
|
515
519
|
particular field.
|
516
520
|
|
517
521
|
|
518
|
-
|
519
|
-
|
520
|
-
the
|
521
|
-
RediSearch doesn't serialize documents that way.
|
522
|
+
While defining the schema you can optionally pass it a block. If no block is
|
523
|
+
passed the `name` will called on the model to get the value. If a block is
|
524
|
+
passed the value for the field is obtained through calling the block.
|
522
525
|
|
523
526
|
```ruby
|
524
527
|
class User < ApplicationRecord
|
525
|
-
redi_search
|
526
|
-
|
527
|
-
|
528
|
-
end
|
529
|
-
|
530
|
-
class UserSerializer < SimpleDelegator
|
531
|
-
def name
|
532
|
-
"#{first_name} #{last_name}"
|
528
|
+
redi_search do
|
529
|
+
text_field :name do
|
530
|
+
"#{first_name} #{last_name}"
|
531
|
+
end
|
533
532
|
end
|
534
533
|
end
|
535
534
|
```
|
@@ -553,13 +552,13 @@ optional `index_prefix` argument which gets prepended to the index name:
|
|
553
552
|
|
554
553
|
```ruby
|
555
554
|
class User < ApplicationRecord
|
556
|
-
redi_search
|
557
|
-
|
558
|
-
|
559
|
-
|
555
|
+
redi_search index_prefix: 'prefix' do
|
556
|
+
text_field :first, phonetic: "dm:en"
|
557
|
+
text_field :last, phonetic: "dm:en"
|
558
|
+
end
|
560
559
|
end
|
561
560
|
|
562
|
-
User.
|
561
|
+
User.search_index.name
|
563
562
|
# => prefix_users_development
|
564
563
|
```
|
565
564
|
|
@@ -568,13 +567,13 @@ after creating and updating and will be removed from the `Index` upon
|
|
568
567
|
destruction.
|
569
568
|
|
570
569
|
There are a few more convenience methods that are publicly available:
|
571
|
-
- `
|
570
|
+
- `search_document`
|
572
571
|
- Returns the record as a `RediSearch::Document` instance
|
573
|
-
- `
|
572
|
+
- `remove_from_index`
|
574
573
|
- Removes the record from the `Index`
|
575
|
-
- `
|
574
|
+
- `add_to_index`
|
576
575
|
- Adds the record to the `Index`
|
577
|
-
- `
|
576
|
+
- `search_index`
|
578
577
|
- Returns the `RediSearch::Index` instance
|
579
578
|
|
580
579
|
|
@@ -608,4 +607,4 @@ The gem is available as open source under the terms of the
|
|
608
607
|
|
609
608
|
Everyone interacting in the RediSearch project’s codebases, issue trackers, chat
|
610
609
|
rooms and mailing lists is expected to follow the [code of
|
611
|
-
conduct](https://github.com/npezza93/redi_search/blob/
|
610
|
+
conduct](https://github.com/npezza93/redi_search/blob/main/CODE_OF_CONDUCT.md).
|
data/bin/console
CHANGED
@@ -19,10 +19,14 @@ ActiveRecord::Migration.create_table :users do |t|
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class User < ActiveRecord::Base
|
22
|
-
redi_search
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
redi_search do
|
23
|
+
text_field :first, phonetic: "dm:en"
|
24
|
+
text_field :last, phonetic: "dm:en"
|
25
|
+
tag_field :tags
|
26
|
+
text_field :name, phonetic: "dm:en" do
|
27
|
+
"#{first} #{last}"
|
28
|
+
end
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
def seed_users(count = 10_000)
|
data/bin/publish
CHANGED
@@ -8,7 +8,7 @@ require_relative "../lib/redi_search/version"
|
|
8
8
|
# path to your application root.
|
9
9
|
APP_ROOT = Pathname.new File.expand_path("..", __dir__)
|
10
10
|
MASTER_CHECK = <<~MASTER_CHECK
|
11
|
-
if [ $(git symbolic-ref --short -q HEAD) != '
|
11
|
+
if [ $(git symbolic-ref --short -q HEAD) != 'main' ];
|
12
12
|
then exit 1;
|
13
13
|
fi
|
14
14
|
MASTER_CHECK
|
@@ -20,7 +20,7 @@ end
|
|
20
20
|
|
21
21
|
abort("\n== Version Type incorrect ==") unless VERSION_TYPES.include?(ARGV[0])
|
22
22
|
|
23
|
-
abort("\n== Not on
|
23
|
+
abort("\n== Not on main") unless system(MASTER_CHECK)
|
24
24
|
|
25
25
|
current_version = RediSearch::VERSION.split(".").map(&:to_i)
|
26
26
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gem "appraisal", "~> 2.2"
|
6
|
+
gem "debug"
|
6
7
|
gem "faker"
|
7
8
|
gem "mocha"
|
8
9
|
gem "rubocop"
|
@@ -10,6 +11,6 @@ gem "rubocop-minitest"
|
|
10
11
|
gem "rubocop-performance"
|
11
12
|
gem "simplecov"
|
12
13
|
gem "sqlite3"
|
13
|
-
gem "activerecord", "~> 7.0.
|
14
|
+
gem "activerecord", "~> 7.0.1"
|
14
15
|
|
15
16
|
gemspec path: "../"
|
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
module RediSearch
|
4
4
|
class AddField
|
5
|
-
def initialize(index,
|
6
|
-
@index
|
7
|
-
@
|
8
|
-
@
|
5
|
+
def initialize(index, name, type, **options, &block)
|
6
|
+
@index = index
|
7
|
+
@name = name
|
8
|
+
@type = type
|
9
|
+
@options = options
|
10
|
+
@block = block
|
9
11
|
end
|
10
12
|
|
11
13
|
def call!
|
12
|
-
index.schema.add_field(
|
14
|
+
field = index.schema.add_field(name, type, **options, &block)
|
13
15
|
|
14
|
-
RediSearch.client.call!(*
|
16
|
+
RediSearch.client.call!("ALTER", index.name, "SCHEMA", "ADD", *field).ok?
|
15
17
|
end
|
16
18
|
|
17
19
|
def call
|
@@ -22,14 +24,6 @@ module RediSearch
|
|
22
24
|
|
23
25
|
private
|
24
26
|
|
25
|
-
attr_reader :index, :
|
26
|
-
|
27
|
-
def command
|
28
|
-
["ALTER", index.name, "SCHEMA", "ADD", *field_schema]
|
29
|
-
end
|
30
|
-
|
31
|
-
def field_schema
|
32
|
-
@field_schema ||= Schema.make_field(field_name, raw_schema).to_a
|
33
|
-
end
|
27
|
+
attr_reader :index, :name, :type, :options, :block
|
34
28
|
end
|
35
29
|
end
|
data/lib/redi_search/client.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
require "redis"
|
4
4
|
require "active_support/notifications"
|
5
5
|
|
6
|
-
require "redi_search/client/response"
|
7
|
-
|
8
6
|
module RediSearch
|
9
7
|
class Client
|
10
8
|
def initialize(redis = Redis.new)
|
@@ -20,9 +18,9 @@ module RediSearch
|
|
20
18
|
end
|
21
19
|
|
22
20
|
def multi
|
23
|
-
Response.new(redis.multi do
|
21
|
+
Response.new(redis.multi do |pipeline|
|
24
22
|
instrument("pipeline", query: ["begin pipeline"])
|
25
|
-
capture_pipeline { yield }
|
23
|
+
capture_pipeline(pipeline) { yield }
|
26
24
|
instrument("pipeline", query: ["finish pipeline"])
|
27
25
|
end)
|
28
26
|
end
|
@@ -32,14 +30,18 @@ module RediSearch
|
|
32
30
|
attr_reader :redis
|
33
31
|
attr_accessor :pipeline
|
34
32
|
|
35
|
-
def capture_pipeline
|
36
|
-
self.pipeline =
|
33
|
+
def capture_pipeline(pipeline)
|
34
|
+
self.pipeline = pipeline
|
37
35
|
yield
|
38
36
|
self.pipeline = false
|
39
37
|
end
|
40
38
|
|
41
39
|
def send_command(command, *params)
|
42
|
-
|
40
|
+
if pipeline
|
41
|
+
Response.new(pipeline.call(command, *params))
|
42
|
+
else
|
43
|
+
Response.new(redis.call(command, *params))
|
44
|
+
end
|
43
45
|
end
|
44
46
|
|
45
47
|
def instrument(action, payload, &block)
|
data/lib/redi_search/document.rb
CHANGED
@@ -1,23 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/document/display"
|
4
|
-
require "redi_search/document/finder"
|
5
|
-
|
6
3
|
module RediSearch
|
7
4
|
class Document
|
8
5
|
include Display
|
9
6
|
|
10
7
|
class << self
|
11
|
-
def for_object(index, record,
|
12
|
-
|
13
|
-
|
14
|
-
field_values = index.schema.fields.map(&:name).filter_map do |field|
|
15
|
-
next unless only.empty? || only.include?(field)
|
8
|
+
def for_object(index, record, only: [])
|
9
|
+
field_values = index.schema.fields.filter_map do |field|
|
10
|
+
next unless only.empty? || only.include?(field.name)
|
16
11
|
|
17
|
-
[field.to_s,
|
12
|
+
[field.name.to_s, field.serialize(record)]
|
18
13
|
end.to_h
|
19
14
|
|
20
|
-
new(index,
|
15
|
+
new(index, record.id, field_values)
|
21
16
|
end
|
22
17
|
|
23
18
|
def get(index, document_id)
|
@@ -48,7 +43,7 @@ module RediSearch
|
|
48
43
|
|
49
44
|
def redis_attributes
|
50
45
|
attributes.flat_map do |field, value|
|
51
|
-
[field, index.schema[field.to_sym].
|
46
|
+
[field, index.schema[field.to_sym].coerce(value)]
|
52
47
|
end
|
53
48
|
end
|
54
49
|
|
data/lib/redi_search/index.rb
CHANGED
@@ -1,19 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/hset"
|
4
|
-
require "redi_search/create"
|
5
|
-
require "redi_search/schema"
|
6
|
-
require "redi_search/search"
|
7
|
-
require "redi_search/spellcheck"
|
8
|
-
require "redi_search/add_field"
|
9
|
-
|
10
3
|
module RediSearch
|
11
4
|
class Index
|
12
5
|
attr_reader :name, :schema, :model
|
13
6
|
|
14
|
-
def initialize(name,
|
7
|
+
def initialize(name, model = nil, &schema)
|
15
8
|
@name = name.to_s
|
16
|
-
@schema = Schema.new(schema)
|
9
|
+
@schema = Schema.new(&schema)
|
17
10
|
@model = model
|
18
11
|
end
|
19
12
|
|
@@ -94,8 +87,8 @@ module RediSearch
|
|
94
87
|
info.num_docs.to_i
|
95
88
|
end
|
96
89
|
|
97
|
-
def add_field(
|
98
|
-
AddField.new(self,
|
90
|
+
def add_field(name, type, **options, &block)
|
91
|
+
AddField.new(self, name, type, **options, &block).call!
|
99
92
|
end
|
100
93
|
|
101
94
|
private
|