redi_search 5.0.0 → 6.0.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 +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
|