redi_search 2.0.2 → 3.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 +8 -10
- data/.github/workflows/tests.yml +14 -13
- data/.rubocop.yml +69 -4
- data/Appraisals +4 -0
- data/Gemfile +1 -0
- data/README.md +15 -33
- data/gemfiles/activerecord_51.gemfile +3 -0
- data/gemfiles/activerecord_52.gemfile +3 -0
- data/gemfiles/activerecord_61.gemfile +16 -0
- data/lib/redi_search/client.rb +16 -6
- data/lib/redi_search/client/response.rb +1 -1
- data/lib/redi_search/create.rb +2 -1
- data/lib/redi_search/document.rb +2 -11
- data/lib/redi_search/document/finder.rb +12 -50
- data/lib/redi_search/hset.rb +28 -0
- data/lib/redi_search/index.rb +18 -16
- data/lib/redi_search/log_subscriber.rb +5 -4
- data/lib/redi_search/model.rb +4 -10
- data/lib/redi_search/search/clauses/boolean.rb +4 -4
- data/lib/redi_search/search/clauses/or.rb +1 -1
- data/lib/redi_search/version.rb +1 -1
- metadata +9 -8
- data/lib/redi_search/add.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3903d2f2ac5a8e6e8c82a507fbef8cad83d11b28a8e68dca6441844dc0b89cd
|
4
|
+
data.tar.gz: 6357b63845acdaea9df5d441154f77a3d5e353b2fed2c5e4cbbe58a5a6ad5071
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94dc557ed0ee0ce1868ef92401928e68442eae74990595bfa26a26de4358f57526a8ef012203b67eae3ddbc6d576a2816b9715f41d140789d8fa3eed6ad09832
|
7
|
+
data.tar.gz: ae05dd2140a22dc5a73e9d90014eb580c0b3bc2276dc515d176efb767cb267a5ffa113cbabbf01fb1b7281e506dbf7798d26f9cbdad167b26afe550e608ecd8d
|
data/.github/workflows/lint.yml
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
name: lint
|
2
2
|
|
3
|
-
on: [push]
|
3
|
+
on: [push,pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
lint:
|
7
7
|
runs-on: ubuntu-latest
|
8
8
|
steps:
|
9
|
-
- uses: actions/checkout@
|
9
|
+
- uses: actions/checkout@v2
|
10
10
|
- name: Set up Ruby 2.7
|
11
|
-
uses:
|
11
|
+
uses: ruby/setup-ruby@v1
|
12
12
|
with:
|
13
|
-
ruby-version: 2.7
|
14
|
-
- name: Install
|
13
|
+
ruby-version: 2.7
|
14
|
+
- name: Install rubocop
|
15
15
|
run: |
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
- name: Run tests
|
20
|
-
run: bundle exec rubocop --config=./.rubocop.yml --parallel
|
16
|
+
gem install rubocop rubocop-performance rubocop-minitest
|
17
|
+
- name: Lint
|
18
|
+
run: rubocop --config=./.rubocop.yml --parallel
|
data/.github/workflows/tests.yml
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
name: tests
|
2
2
|
|
3
|
-
on: [push]
|
3
|
+
on: [push,pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
unit:
|
7
7
|
runs-on: ubuntu-latest
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby: [ '2.5
|
11
|
-
gemfile: [ 'Gemfile', 'gemfiles/activerecord_51.gemfile', 'gemfiles/activerecord_52.gemfile' ]
|
10
|
+
ruby: [ '2.5', '2.6', '2.7' ]
|
11
|
+
gemfile: [ 'Gemfile', 'gemfiles/activerecord_51.gemfile', 'gemfiles/activerecord_52.gemfile', 'gemfiles/activerecord_61.gemfile' ]
|
12
12
|
steps:
|
13
|
-
- uses: actions/checkout@
|
13
|
+
- uses: actions/checkout@v2
|
14
14
|
- name: Set up Ruby ${{ matrix.ruby }}
|
15
|
-
uses:
|
15
|
+
uses: ruby/setup-ruby@v1
|
16
16
|
with:
|
17
17
|
ruby-version: ${{ matrix.ruby }}
|
18
|
+
bundler-cache: false
|
18
19
|
- name: Install dependencies
|
19
20
|
run: |
|
20
21
|
sudo apt-get install libsqlite3-dev -y
|
@@ -24,21 +25,21 @@ jobs:
|
|
24
25
|
run: BUNDLE_GEMFILE=${{ matrix.gemfile }} bundle exec rake test:unit
|
25
26
|
integration:
|
26
27
|
runs-on: ubuntu-latest
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
services:
|
29
|
+
redisearch:
|
30
|
+
image: redislabs/redisearch:2.0.2
|
31
|
+
ports:
|
32
|
+
- 6379:6379
|
30
33
|
steps:
|
31
|
-
- uses: actions/checkout@
|
34
|
+
- uses: actions/checkout@v2
|
32
35
|
- name: Set up Ruby 2.7
|
33
|
-
uses:
|
36
|
+
uses: ruby/setup-ruby@v1
|
34
37
|
with:
|
35
|
-
ruby-version: 2.7
|
38
|
+
ruby-version: 2.7
|
36
39
|
- name: Install dependencies
|
37
40
|
run: |
|
38
41
|
sudo apt-get install libsqlite3-dev -y
|
39
|
-
gem install bundler --no-document
|
40
42
|
bundle install
|
41
|
-
docker run -d -p 6379:6379 redislabs/redisearch:${{ matrix.redi_search }} --protected-mode no --loadmodule /usr/lib/redis/modules/redisearch.so
|
42
43
|
- name: Run tests
|
43
44
|
run: |
|
44
45
|
bundle exec rake test:integration
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require:
|
2
|
+
- rubocop-minitest
|
2
3
|
- rubocop-performance
|
3
4
|
AllCops:
|
5
|
+
NewCops: enable
|
4
6
|
Exclude:
|
5
7
|
- vendor/**/*
|
6
8
|
- Gemfile.lock
|
@@ -9,6 +11,7 @@ AllCops:
|
|
9
11
|
- tmp/**/*
|
10
12
|
- test/dummy/db/schema.rb
|
11
13
|
- gemfiles/**/*
|
14
|
+
- bin/**/*
|
12
15
|
TargetRubyVersion: 2.5
|
13
16
|
|
14
17
|
# Department Bundler
|
@@ -611,7 +614,7 @@ Lint/UselessAssignment:
|
|
611
614
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars
|
612
615
|
Enabled: true
|
613
616
|
|
614
|
-
Lint/
|
617
|
+
Lint/BinaryOperatorWithIdenticalOperands:
|
615
618
|
Description: Checks for comparison of something with itself.
|
616
619
|
Enabled: true
|
617
620
|
|
@@ -1197,9 +1200,6 @@ Style/MethodDefParentheses:
|
|
1197
1200
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#method-parens
|
1198
1201
|
Enabled: true
|
1199
1202
|
|
1200
|
-
Style/MethodMissingSuper:
|
1201
|
-
Enabled: true
|
1202
|
-
|
1203
1203
|
Style/MissingRespondToMissing:
|
1204
1204
|
Enabled: true
|
1205
1205
|
|
@@ -1630,5 +1630,70 @@ Style/RedundantRegexpCharacterClass:
|
|
1630
1630
|
Enabled: true
|
1631
1631
|
Style/RedundantRegexpEscape:
|
1632
1632
|
Enabled: true
|
1633
|
+
Lint/MissingSuper:
|
1634
|
+
Enabled: false
|
1635
|
+
|
1636
|
+
|
1637
|
+
|
1638
|
+
Lint/DuplicateElsifCondition:
|
1639
|
+
Enabled: true
|
1640
|
+
Lint/DuplicateRescueException:
|
1641
|
+
Enabled: true
|
1642
|
+
Lint/EmptyConditionalBody:
|
1643
|
+
Enabled: true
|
1644
|
+
Lint/FloatComparison:
|
1645
|
+
Enabled: true
|
1646
|
+
Lint/OutOfRangeRegexpRef:
|
1647
|
+
Enabled: true
|
1648
|
+
Lint/SelfAssignment:
|
1649
|
+
Enabled: true
|
1650
|
+
Lint/TopLevelReturnWithArgument:
|
1651
|
+
Enabled: true
|
1652
|
+
Lint/UnreachableLoop:
|
1653
|
+
Enabled: true
|
1654
|
+
Style/AccessorGrouping:
|
1655
|
+
Enabled: true
|
1656
|
+
Style/ArrayCoercion:
|
1657
|
+
Enabled: true
|
1658
|
+
Style/BisectedAttrAccessor:
|
1659
|
+
Enabled: true
|
1660
|
+
Style/CaseLikeIf:
|
1661
|
+
Enabled: true
|
1662
|
+
Style/ExplicitBlockArgument:
|
1663
|
+
Enabled: false
|
1664
|
+
Style/GlobalStdStream:
|
1665
|
+
Enabled: true
|
1666
|
+
Style/HashAsLastArrayItem:
|
1667
|
+
Enabled: false
|
1668
|
+
Style/HashLikeCase:
|
1669
|
+
Enabled: true
|
1670
|
+
Style/OptionalBooleanParameter:
|
1671
|
+
Enabled: true
|
1672
|
+
Style/RedundantAssignment:
|
1673
|
+
Enabled: true
|
1633
1674
|
Style/RedundantFetchBlock:
|
1634
1675
|
Enabled: true
|
1676
|
+
Style/RedundantFileExtensionInRequire:
|
1677
|
+
Enabled: true
|
1678
|
+
Style/SingleArgumentDig:
|
1679
|
+
Enabled: true
|
1680
|
+
Style/StringConcatenation:
|
1681
|
+
Enabled: true
|
1682
|
+
Performance/AncestorsInclude:
|
1683
|
+
Enabled: true
|
1684
|
+
Performance/BigDecimalWithNumericArgument:
|
1685
|
+
Enabled: true
|
1686
|
+
Performance/RedundantSortBlock:
|
1687
|
+
Enabled: true
|
1688
|
+
Performance/RedundantStringChars:
|
1689
|
+
Enabled: true
|
1690
|
+
Performance/ReverseFirst:
|
1691
|
+
Enabled: true
|
1692
|
+
Performance/SortReverse:
|
1693
|
+
Enabled: true
|
1694
|
+
Performance/Squeeze:
|
1695
|
+
Enabled: true
|
1696
|
+
Performance/StringInclude:
|
1697
|
+
Enabled: true
|
1698
|
+
Minitest/AssertionInLifecycleHook:
|
1699
|
+
Enabled: false
|
data/Appraisals
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
# RediSearch
|
8
8
|
|
9
9
|
![Build Status](https://github.com/npezza93/redi_search/workflows/tests/badge.svg)
|
10
|
-
[![Test Coverage](https://api.codeclimate.com/v1/badges/c6437acac5684de2549d/test_coverage)](https://codeclimate.com/github/npezza93/redi_search/test_coverage)
|
11
10
|
[![Maintainability](https://api.codeclimate.com/v1/badges/c6437acac5684de2549d/maintainability)](https://codeclimate.com/github/npezza93/redi_search/maintainability)
|
12
11
|
|
13
12
|
A simple, but powerful, Ruby wrapper around RediSearch, a search engine on top of
|
@@ -244,13 +243,11 @@ With no options: `{ place: :geo }`
|
|
244
243
|
|
245
244
|
## Document
|
246
245
|
|
247
|
-
A `Document` is the Ruby representation of a
|
246
|
+
A `Document` is the Ruby representation of a Redis hash.
|
248
247
|
|
249
|
-
You can fetch a `Document` using `.get`
|
248
|
+
You can fetch a `Document` using `.get` class methods.
|
250
249
|
- `get(index, document_id)` fetches a single `Document` in an `Index` for a
|
251
250
|
given `document_id`.
|
252
|
-
- `mget(index, *document_ids)` fetches a collection of `Document`s
|
253
|
-
in an `Index` for the given `document_ids`.
|
254
251
|
|
255
252
|
You can also make a `Document` instance using the
|
256
253
|
`.for_object(index, record, serializer: nil, only: [])` class method. It takes
|
@@ -269,10 +266,7 @@ to override each other. There is also a `#document_id_without_index` method
|
|
269
266
|
which removes the prepended index name.
|
270
267
|
|
271
268
|
Finally there is a `#del` method that will remove the `Document` from the
|
272
|
-
`Index`.
|
273
|
-
whether the `Document` should be completely removed from the Redis instance vs
|
274
|
-
just the `Index`.
|
275
|
-
|
269
|
+
`Index`.
|
276
270
|
|
277
271
|
## Index
|
278
272
|
|
@@ -314,42 +308,32 @@ RediSearch::Index.new(name_of_index, schema)
|
|
314
308
|
- If set, we avoid saving the term frequencies in the index. This saves
|
315
309
|
memory but does not allow sorting based on the frequencies of a given
|
316
310
|
term within the document.
|
317
|
-
- `drop`
|
311
|
+
- `drop(keep_docs: false)`
|
318
312
|
- Drops the `Index` from the Redis instance, returns a boolean. Has an
|
319
313
|
accompanying bang method that will raise an exception upon failure. Will
|
320
|
-
return `false` if the `Index` has already been dropped.
|
314
|
+
return `false` if the `Index` has already been dropped. Takes an option
|
315
|
+
keyword arg, `keep_docs`, that will by default remove all the document
|
316
|
+
hashes in Redis.
|
321
317
|
- `exist?`
|
322
318
|
- Returns a boolean signifying `Index` existence.
|
323
319
|
- `info`
|
324
320
|
- Returns a struct object with all the information about the `Index`.
|
325
321
|
- `fields`
|
326
322
|
- Returns an array of the field names in the `Index`.
|
327
|
-
- `add(document
|
328
|
-
- Takes a `Document` object
|
323
|
+
- `add(document)`
|
324
|
+
- Takes a `Document` object. Has an
|
329
325
|
accompanying bang method that will raise an exception upon failure.
|
330
|
-
|
331
|
-
- `language` -> Use a stemmer for the supplied language during indexing.
|
332
|
-
- `no_save` -> Don't save the actual `Document` in the database and only index it.
|
333
|
-
- `replace` -> Accepts a boolean or a hash. If a truthy value is passed, we
|
334
|
-
will do an UPSERT style insertion - and delete an older version of the
|
335
|
-
`Document` if it exists.
|
336
|
-
- `replace: { partial: true }` -> Allows you to not have to specify all
|
337
|
-
fields for reindexing. Fields not given to the command will be loaded from
|
338
|
-
the current version of the `Document`.
|
339
|
-
- `add_multiple(documents, score: 1.0, replace: {}, language: nil, no_save: false)`
|
326
|
+
- `add_multiple(documents)`
|
340
327
|
- Takes an array of `Document` objects. This provides a more performant way to
|
341
328
|
add multiple documents to the `Index`. Accepts the same options as `add`.
|
342
|
-
- `del(document
|
343
|
-
- Removes a `Document` from the `Index`.
|
344
|
-
`Document` should be completely removed from the Redis instance vs just the
|
345
|
-
`Index`.
|
329
|
+
- `del(document)`
|
330
|
+
- Removes a `Document` from the `Index`.
|
346
331
|
- `document_count`
|
347
332
|
- Returns the number of `Document`s in the `Index`
|
348
333
|
- `add_field(field_name, schema)`
|
349
334
|
- Adds a new field to the `Index`. Ex: `index.add_field(:first_name, text: { phonetic: "dm:en" })`
|
350
|
-
- `reindex(documents, recreate: false
|
335
|
+
- `reindex(documents, recreate: false)`
|
351
336
|
- If `recreate` is `true` the `Index` will be dropped and recreated
|
352
|
-
- `options` accepts the same options as `add`
|
353
337
|
|
354
338
|
|
355
339
|
## Searching
|
@@ -521,11 +505,9 @@ end
|
|
521
505
|
This will automatically add `User.search` and `User.spellcheck`
|
522
506
|
methods which behave the same as if you called them on an `Index` instance.
|
523
507
|
|
524
|
-
`User.reindex(recreate: false, only: []
|
508
|
+
`User.reindex(recreate: false, only: [])` is also added and behaves
|
525
509
|
similarly to `RediSearch::Index#reindex`. Some of the differences include:
|
526
|
-
-
|
527
|
-
option `replace: { partial: true }`.
|
528
|
-
- `Document`s do not to be passed as the first parameter. The `search_import`
|
510
|
+
- `Document`s do not need to be passed as the first parameter. The `search_import`
|
529
511
|
scope is automatically called and all the records are converted
|
530
512
|
to `Document`s.
|
531
513
|
- Accepts an optional `only` parameter where you can specify a limited number
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "appraisal", "~> 2.2"
|
6
|
+
gem "faker"
|
7
|
+
gem "mocha"
|
8
|
+
gem "pry"
|
9
|
+
gem "rubocop"
|
10
|
+
gem "rubocop-minitest"
|
11
|
+
gem "rubocop-performance"
|
12
|
+
gem "simplecov"
|
13
|
+
gem "sqlite3"
|
14
|
+
gem "activerecord", "6.1.0.rc1"
|
15
|
+
|
16
|
+
gemspec path: "../"
|
data/lib/redi_search/client.rb
CHANGED
@@ -9,10 +9,12 @@ module RediSearch
|
|
9
9
|
class Client
|
10
10
|
def initialize(redis = Redis.new)
|
11
11
|
@redis = redis
|
12
|
+
@pipeline = false
|
12
13
|
end
|
13
14
|
|
14
|
-
def call!(command, *params)
|
15
|
+
def call!(command, *params, skip_ft: false)
|
15
16
|
instrument(command.downcase, query: [command, params]) do
|
17
|
+
command = "FT.#{command}" unless skip_ft
|
16
18
|
send_command(command, *params)
|
17
19
|
end
|
18
20
|
end
|
@@ -20,24 +22,32 @@ module RediSearch
|
|
20
22
|
def multi
|
21
23
|
Response.new(redis.multi do
|
22
24
|
instrument("pipeline", query: ["begin pipeline"])
|
23
|
-
yield
|
25
|
+
capture_pipeline { yield }
|
24
26
|
instrument("pipeline", query: ["finish pipeline"])
|
25
27
|
end)
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
29
31
|
|
30
|
-
attr_reader
|
32
|
+
attr_reader :redis
|
33
|
+
attr_accessor :pipeline
|
34
|
+
|
35
|
+
def capture_pipeline
|
36
|
+
self.pipeline = true
|
37
|
+
yield
|
38
|
+
self.pipeline = false
|
39
|
+
end
|
31
40
|
|
32
41
|
def send_command(command, *params)
|
33
|
-
Response.new(redis.call(
|
42
|
+
Response.new(redis.call(command, *params))
|
34
43
|
end
|
35
44
|
|
36
45
|
def instrument(action, payload, &block)
|
37
46
|
ActiveSupport::Notifications.instrument(
|
38
47
|
"action.redi_search",
|
39
|
-
{ name: "RediSearch", action: action }.
|
40
|
-
|
48
|
+
{ name: "RediSearch", action: action, inside_pipeline: pipeline }.
|
49
|
+
merge(payload),
|
50
|
+
&Proc.new(&(block || proc {})) # rubocop:disable Lint/EmptyBlock
|
41
51
|
)
|
42
52
|
end
|
43
53
|
end
|
data/lib/redi_search/create.rb
CHANGED
@@ -31,7 +31,8 @@ module RediSearch
|
|
31
31
|
attr_reader :index, :schema, :options
|
32
32
|
|
33
33
|
def command
|
34
|
-
["CREATE", index.name,
|
34
|
+
["CREATE", index.name, "ON", "HASH", "PREFIX", 1, index.name,
|
35
|
+
*extract_options.compact, "SCHEMA", schema.to_a]
|
35
36
|
end
|
36
37
|
|
37
38
|
def extract_options
|
data/lib/redi_search/document.rb
CHANGED
@@ -23,10 +23,6 @@ module RediSearch
|
|
23
23
|
def get(index, document_id)
|
24
24
|
Finder.new(index, document_id).find
|
25
25
|
end
|
26
|
-
|
27
|
-
def mget(index, *document_ids)
|
28
|
-
Finder.new(index, *document_ids).find
|
29
|
-
end
|
30
26
|
end
|
31
27
|
|
32
28
|
attr_reader :attributes, :score
|
@@ -40,9 +36,8 @@ module RediSearch
|
|
40
36
|
load_attributes
|
41
37
|
end
|
42
38
|
|
43
|
-
def del
|
44
|
-
|
45
|
-
call!(*command.compact).ok?
|
39
|
+
def del
|
40
|
+
RediSearch.client.call!("DEL", document_id, skip_ft: true).ok?
|
46
41
|
end
|
47
42
|
|
48
43
|
def schema_fields
|
@@ -73,10 +68,6 @@ module RediSearch
|
|
73
68
|
|
74
69
|
attr_reader :index
|
75
70
|
|
76
|
-
def call!(*command)
|
77
|
-
RediSearch.client.call!(*command)
|
78
|
-
end
|
79
|
-
|
80
71
|
def load_attributes
|
81
72
|
attributes.each do |field, value|
|
82
73
|
next unless schema_fields.include? field.to_s
|
@@ -3,75 +3,37 @@
|
|
3
3
|
module RediSearch
|
4
4
|
class Document
|
5
5
|
class Finder
|
6
|
-
def initialize(index,
|
6
|
+
def initialize(index, document_id)
|
7
7
|
@index = index
|
8
|
-
@
|
8
|
+
@document_id = document_id
|
9
9
|
end
|
10
10
|
|
11
11
|
def find
|
12
|
-
if
|
13
|
-
parse_multi_documents
|
14
|
-
else
|
15
|
-
parse_document(document_ids.first, response)
|
16
|
-
end
|
12
|
+
Document.new(index, document_id, Hash[*response]) if response?
|
17
13
|
end
|
18
14
|
|
19
15
|
private
|
20
16
|
|
21
|
-
attr_reader :index, :
|
17
|
+
attr_reader :index, :document_id
|
22
18
|
|
23
19
|
def response
|
24
|
-
@response ||= call!(
|
20
|
+
@response ||= call!("HGETALL", prepended_document_id)
|
25
21
|
end
|
26
22
|
|
27
23
|
def call!(*command)
|
28
|
-
RediSearch.client.call!(*command)
|
29
|
-
end
|
30
|
-
|
31
|
-
def get_command
|
32
|
-
if multi?
|
33
|
-
"MGET"
|
34
|
-
else
|
35
|
-
"GET"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def multi?
|
40
|
-
document_ids.size > 1
|
41
|
-
end
|
42
|
-
|
43
|
-
def prepended_document_ids
|
44
|
-
document_ids.map do |document_id|
|
45
|
-
prepend_document_id(document_id)
|
46
|
-
end
|
24
|
+
RediSearch.client.call!(*command, skip_ft: true)
|
47
25
|
end
|
48
26
|
|
49
|
-
def
|
50
|
-
if
|
51
|
-
|
27
|
+
def prepended_document_id
|
28
|
+
if document_id.to_s.start_with? index.name
|
29
|
+
document_id
|
52
30
|
else
|
53
|
-
"#{index.name}#{
|
31
|
+
"#{index.name}#{document_id}"
|
54
32
|
end
|
55
33
|
end
|
56
34
|
|
57
|
-
def
|
58
|
-
|
59
|
-
parse_document(document_id, response[index])
|
60
|
-
end.compact
|
61
|
-
end
|
62
|
-
|
63
|
-
def parse_document(document_id, document_response)
|
64
|
-
return unless document_response?(document_response)
|
65
|
-
|
66
|
-
Document.new(index, document_id, Hash[*document_response])
|
67
|
-
end
|
68
|
-
|
69
|
-
def document_response?(document_response)
|
70
|
-
if document_response.respond_to?(:empty?)
|
71
|
-
!document_response.empty?
|
72
|
-
else
|
73
|
-
!document_response.nil?
|
74
|
-
end
|
35
|
+
def response?
|
36
|
+
!response.to_a.empty?
|
75
37
|
end
|
76
38
|
end
|
77
39
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RediSearch
|
4
|
+
class Hset
|
5
|
+
def initialize(index, document)
|
6
|
+
@index = index
|
7
|
+
@document = document
|
8
|
+
end
|
9
|
+
|
10
|
+
def call!
|
11
|
+
RediSearch.client.call!(*command, skip_ft: true)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
call!
|
16
|
+
rescue Redis::CommandError
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :index, :document
|
23
|
+
|
24
|
+
def command
|
25
|
+
["HSET", document.document_id, document.redis_attributes].compact
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/redi_search/index.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/
|
3
|
+
require "redi_search/hset"
|
4
4
|
require "redi_search/create"
|
5
5
|
require "redi_search/schema"
|
6
6
|
require "redi_search/search"
|
@@ -33,34 +33,36 @@ module RediSearch
|
|
33
33
|
Create.new(self, schema, options).call!
|
34
34
|
end
|
35
35
|
|
36
|
-
def drop
|
37
|
-
drop!
|
36
|
+
def drop(keep_docs: false)
|
37
|
+
drop!(keep_docs: keep_docs)
|
38
38
|
rescue Redis::CommandError
|
39
39
|
false
|
40
40
|
end
|
41
41
|
|
42
|
-
def drop!
|
43
|
-
|
42
|
+
def drop!(keep_docs: false)
|
43
|
+
command = ["DROPINDEX", name]
|
44
|
+
command << "DD" unless keep_docs
|
45
|
+
client.call!(*command.compact).ok?
|
44
46
|
end
|
45
47
|
|
46
|
-
def add(document
|
47
|
-
|
48
|
+
def add(document)
|
49
|
+
Hset.new(self, document).call
|
48
50
|
end
|
49
51
|
|
50
|
-
def add!(document
|
51
|
-
|
52
|
+
def add!(document)
|
53
|
+
Hset.new(self, document).call!
|
52
54
|
end
|
53
55
|
|
54
|
-
def add_multiple(documents
|
56
|
+
def add_multiple(documents)
|
55
57
|
client.multi do
|
56
58
|
documents.each do |document|
|
57
|
-
add(document
|
59
|
+
add(document)
|
58
60
|
end
|
59
|
-
end.
|
61
|
+
end.all? { |response| response >= 0 }
|
60
62
|
end
|
61
63
|
|
62
|
-
def del(document
|
63
|
-
document.del
|
64
|
+
def del(document)
|
65
|
+
document.del
|
64
66
|
end
|
65
67
|
|
66
68
|
def exist?
|
@@ -81,11 +83,11 @@ module RediSearch
|
|
81
83
|
schema.fields.map(&:to_s)
|
82
84
|
end
|
83
85
|
|
84
|
-
def reindex(documents, recreate: false
|
86
|
+
def reindex(documents, recreate: false)
|
85
87
|
drop if recreate
|
86
88
|
create unless exist?
|
87
89
|
|
88
|
-
add_multiple documents
|
90
|
+
add_multiple documents
|
89
91
|
end
|
90
92
|
|
91
93
|
def document_count
|
@@ -39,9 +39,9 @@ module RediSearch
|
|
39
39
|
def action_color(action)
|
40
40
|
case action.to_sym
|
41
41
|
when :search, :spellcheck then YELLOW
|
42
|
-
when :create, :
|
43
|
-
when :
|
44
|
-
when :
|
42
|
+
when :create, :hset then GREEN
|
43
|
+
when :dropindex, :del then RED
|
44
|
+
when :hgetall, :info then CYAN
|
45
45
|
when :pipeline then MAGENTA
|
46
46
|
when :explaincli then BLUE
|
47
47
|
end
|
@@ -52,6 +52,7 @@ module RediSearch
|
|
52
52
|
event.payload[:query].flatten.map.with_index do |arg, i|
|
53
53
|
arg = "FT.#{arg}" if prepend_ft?(arg, i)
|
54
54
|
arg = arg.inspect if inspect_arg?(event.payload, arg)
|
55
|
+
arg = " #{arg}" if event.payload[:inside_pipeline]
|
55
56
|
arg
|
56
57
|
end.join(" ")
|
57
58
|
end
|
@@ -61,7 +62,7 @@ module RediSearch
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def prepend_ft?(arg, index)
|
64
|
-
index.zero? && !multiword?(arg)
|
65
|
+
index.zero? && !multiword?(arg) && %w(HSET HGETALL DEL).exclude?(arg.to_s)
|
65
66
|
end
|
66
67
|
|
67
68
|
def inspect_arg?(payload, arg)
|
data/lib/redi_search/model.rb
CHANGED
@@ -48,11 +48,11 @@ module RediSearch
|
|
48
48
|
redi_search_index.spellcheck(term, distance: distance)
|
49
49
|
end
|
50
50
|
|
51
|
-
def reindex(recreate: false, only: []
|
51
|
+
def reindex(recreate: false, only: [])
|
52
52
|
search_import.find_in_batches.all? do |group|
|
53
53
|
redi_search_index.reindex(
|
54
54
|
group.map { |record| record.redi_search_document(only: only) },
|
55
|
-
recreate: recreate
|
55
|
+
recreate: recreate
|
56
56
|
)
|
57
57
|
end
|
58
58
|
end
|
@@ -67,17 +67,11 @@ module RediSearch
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def redi_search_delete_document
|
70
|
-
|
71
|
-
|
72
|
-
self.class.redi_search_index.del(
|
73
|
-
redi_search_document, delete_document: true
|
74
|
-
)
|
70
|
+
self.class.redi_search_index.del(redi_search_document)
|
75
71
|
end
|
76
72
|
|
77
73
|
def redi_search_add_document
|
78
|
-
|
79
|
-
|
80
|
-
self.class.redi_search_index.add(redi_search_document, replace: true)
|
74
|
+
self.class.redi_search_index.add(redi_search_document)
|
81
75
|
end
|
82
76
|
end
|
83
77
|
end
|
@@ -48,7 +48,7 @@ module RediSearch
|
|
48
48
|
@term = if term.is_a? RediSearch::Search
|
49
49
|
term
|
50
50
|
else
|
51
|
-
Term.new(term, term_options)
|
51
|
+
Term.new(term, **term_options)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -65,10 +65,10 @@ module RediSearch
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def queryify_search
|
68
|
-
if
|
69
|
-
"(#{term.term_clause})"
|
70
|
-
else
|
68
|
+
if term.term_clause.is_a?(RediSearch::Search::Clauses::Where)
|
71
69
|
term.term_clause
|
70
|
+
else
|
71
|
+
"(#{term.term_clause})"
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
data/lib/redi_search/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redi_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Pezza
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
- - "~>"
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: '13.0'
|
101
|
-
description:
|
101
|
+
description:
|
102
102
|
email: npezza93@gmail.com
|
103
103
|
executables: []
|
104
104
|
extensions: []
|
@@ -123,8 +123,8 @@ files:
|
|
123
123
|
- gemfiles/.bundle/config
|
124
124
|
- gemfiles/activerecord_51.gemfile
|
125
125
|
- gemfiles/activerecord_52.gemfile
|
126
|
+
- gemfiles/activerecord_61.gemfile
|
126
127
|
- lib/redi_search.rb
|
127
|
-
- lib/redi_search/add.rb
|
128
128
|
- lib/redi_search/add_field.rb
|
129
129
|
- lib/redi_search/client.rb
|
130
130
|
- lib/redi_search/client/response.rb
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/redi_search/document.rb
|
134
134
|
- lib/redi_search/document/display.rb
|
135
135
|
- lib/redi_search/document/finder.rb
|
136
|
+
- lib/redi_search/hset.rb
|
136
137
|
- lib/redi_search/index.rb
|
137
138
|
- lib/redi_search/lazily_load.rb
|
138
139
|
- lib/redi_search/log_subscriber.rb
|
@@ -179,7 +180,7 @@ metadata:
|
|
179
180
|
homepage_uri: https://github.com/npezza93/redi_search
|
180
181
|
source_code_uri: https://github.com/npezza93/redi_search
|
181
182
|
changelog_uri: https://github.com/npezza93/redi_search/releases
|
182
|
-
post_install_message:
|
183
|
+
post_install_message:
|
183
184
|
rdoc_options: []
|
184
185
|
require_paths:
|
185
186
|
- lib
|
@@ -194,8 +195,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
195
|
- !ruby/object:Gem::Version
|
195
196
|
version: '0'
|
196
197
|
requirements: []
|
197
|
-
rubygems_version: 3.1.
|
198
|
-
signing_key:
|
198
|
+
rubygems_version: 3.1.4
|
199
|
+
signing_key:
|
199
200
|
specification_version: 4
|
200
201
|
summary: RediSearch ruby wrapper that can integrate with Rails
|
201
202
|
test_files: []
|
data/lib/redi_search/add.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "redi_search/validatable"
|
4
|
-
|
5
|
-
module RediSearch
|
6
|
-
class Add
|
7
|
-
include Validatable
|
8
|
-
|
9
|
-
validates_numericality_of :score, within: 0.0..1.0
|
10
|
-
|
11
|
-
def initialize(index, document, score: 1.0, replace: {}, language: nil,
|
12
|
-
no_save: false)
|
13
|
-
@index = index
|
14
|
-
@document = document
|
15
|
-
@score = score || 1.0
|
16
|
-
@replace = replace
|
17
|
-
@language = language
|
18
|
-
@no_save = no_save
|
19
|
-
end
|
20
|
-
|
21
|
-
def call!
|
22
|
-
validate!
|
23
|
-
|
24
|
-
RediSearch.client.call!(*command).ok?
|
25
|
-
end
|
26
|
-
|
27
|
-
def call
|
28
|
-
call!
|
29
|
-
rescue Redis::CommandError
|
30
|
-
false
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
attr_reader :index, :document, :score, :replace, :language, :no_save
|
36
|
-
|
37
|
-
def command
|
38
|
-
["ADD", index.name, document.document_id, score, *extract_options,
|
39
|
-
"FIELDS", document.redis_attributes].compact
|
40
|
-
end
|
41
|
-
|
42
|
-
def extract_options
|
43
|
-
opts = []
|
44
|
-
opts << ["LANGUAGE", language] if language
|
45
|
-
opts << "NOSAVE" if no_save
|
46
|
-
opts << replace_options if replace?
|
47
|
-
opts
|
48
|
-
end
|
49
|
-
|
50
|
-
def replace?
|
51
|
-
if replace.respond_to?(:empty?)
|
52
|
-
!replace.empty?
|
53
|
-
else
|
54
|
-
replace
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def replace_options
|
59
|
-
["REPLACE"].tap do |replace_option|
|
60
|
-
if replace.is_a?(Hash)
|
61
|
-
replace_option << "PARTIAL" if replace[:partial]
|
62
|
-
# replace_option << "NOCREATE" if replace[:no_create]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|