redi_search 3.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 +8 -4
- data/.github/workflows/tests.yml +13 -6
- data/.rubocop.yml +2 -1
- data/Appraisals +6 -6
- data/Gemfile +3 -2
- data/README.md +57 -58
- data/Rakefile +1 -0
- data/bin/console +14 -6
- data/bin/publish +2 -2
- data/gemfiles/{activerecord_52.gemfile → activerecord_60.gemfile} +2 -2
- data/gemfiles/activerecord_61.gemfile +2 -2
- data/gemfiles/{activerecord_51.gemfile → activerecord_70.gemfile} +2 -2
- data/lib/redi_search/add_field.rb +9 -15
- data/lib/redi_search/client.rb +10 -8
- data/lib/redi_search/document/display.rb +4 -4
- data/lib/redi_search/document.rb +12 -13
- data/lib/redi_search/index.rb +5 -12
- data/lib/redi_search/lazily_load.rb +2 -2
- data/lib/redi_search/log_subscriber.rb +2 -2
- data/lib/redi_search/model.rb +20 -28
- data/lib/redi_search/schema/field.rb +24 -2
- data/lib/redi_search/schema/geo_field.rb +6 -7
- data/lib/redi_search/schema/numeric_field.rb +6 -7
- data/lib/redi_search/schema/tag_field.rb +16 -8
- data/lib/redi_search/schema/text_field.rb +8 -7
- data/lib/redi_search/schema.rb +35 -22
- 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/result.rb +2 -2
- data/lib/redi_search/search/term.rb +16 -9
- data/lib/redi_search/search.rb +1 -7
- data/lib/redi_search/spellcheck/result.rb +4 -4
- data/lib/redi_search/spellcheck.rb +3 -7
- 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 +11 -8
- metadata +24 -9
@@ -4,9 +4,9 @@ module RediSearch
|
|
4
4
|
class Document
|
5
5
|
module Display
|
6
6
|
def inspect
|
7
|
-
inspection = pretty_print_attributes.
|
7
|
+
inspection = pretty_print_attributes.filter_map do |field_name|
|
8
8
|
"#{field_name}: #{public_send(field_name)}"
|
9
|
-
end.
|
9
|
+
end.join(", ")
|
10
10
|
|
11
11
|
"#<#{self.class} #{inspection}>"
|
12
12
|
end
|
@@ -19,7 +19,7 @@ module RediSearch
|
|
19
19
|
pp_attrs.compact
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
# :nocov:
|
23
23
|
def pretty_print(printer) # rubocop:disable Metrics/MethodLength
|
24
24
|
printer.object_address_group(self) do
|
25
25
|
printer.seplist(
|
@@ -35,7 +35,7 @@ module RediSearch
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
# :nocov:
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
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 do |field|
|
15
|
-
next unless only.empty? || only.include?(field.to_sym)
|
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,
|
18
|
-
end.
|
12
|
+
[field.name.to_s, field.serialize(record)]
|
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)
|
@@ -41,11 +36,15 @@ module RediSearch
|
|
41
36
|
end
|
42
37
|
|
43
38
|
def schema_fields
|
44
|
-
@schema_fields ||= index.schema.fields.map
|
39
|
+
@schema_fields ||= index.schema.fields.map do |field|
|
40
|
+
field.name.to_s
|
41
|
+
end
|
45
42
|
end
|
46
43
|
|
47
44
|
def redis_attributes
|
48
|
-
attributes.
|
45
|
+
attributes.flat_map do |field, value|
|
46
|
+
[field, index.schema[field.to_sym].coerce(value)]
|
47
|
+
end
|
49
48
|
end
|
50
49
|
|
51
50
|
def document_id
|
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
|
|
@@ -80,7 +73,7 @@ module RediSearch
|
|
80
73
|
end
|
81
74
|
|
82
75
|
def fields
|
83
|
-
schema.fields.map
|
76
|
+
schema.fields.map { |field| field.name.to_s }
|
84
77
|
end
|
85
78
|
|
86
79
|
def reindex(documents, recreate: false)
|
@@ -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
|
@@ -30,7 +30,7 @@ module RediSearch
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
# :nocov:
|
34
34
|
def pretty_print(printer)
|
35
35
|
execute_and_rescue_inspection do
|
36
36
|
return super(inspect) unless valid?
|
@@ -38,7 +38,7 @@ module RediSearch
|
|
38
38
|
printer.pp(documents)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
# :nocov:
|
42
42
|
|
43
43
|
private
|
44
44
|
|
@@ -12,12 +12,12 @@ module RediSearch
|
|
12
12
|
Thread.current[:redi_search_runtime] ||= 0
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
# :nocov:
|
16
16
|
def self.reset_runtime
|
17
17
|
rt, self.runtime = runtime, 0
|
18
18
|
rt
|
19
19
|
end
|
20
|
-
|
20
|
+
# :nocov:
|
21
21
|
|
22
22
|
def action(event)
|
23
23
|
self.class.runtime += event.duration
|
data/lib/redi_search/model.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/index"
|
4
|
-
|
5
3
|
module RediSearch
|
6
4
|
module Model
|
7
5
|
def self.included(base)
|
@@ -9,18 +7,16 @@ module RediSearch
|
|
9
7
|
end
|
10
8
|
|
11
9
|
module ClassMethods
|
12
|
-
attr_reader :
|
10
|
+
attr_reader :search_index
|
13
11
|
|
14
12
|
# rubocop:disable Metrics/MethodLength
|
15
|
-
def redi_search(
|
16
|
-
@
|
17
|
-
[options[:index_prefix],
|
18
|
-
|
19
|
-
schema
|
20
|
-
self
|
13
|
+
def redi_search(**options, &schema)
|
14
|
+
@search_index = Index.new(
|
15
|
+
[options[:index_prefix], model_name.plural, RediSearch.env].
|
16
|
+
compact.join("_"),
|
17
|
+
self, &schema
|
21
18
|
)
|
22
|
-
|
23
|
-
register_redi_search_commit_hooks
|
19
|
+
register_search_commit_hooks
|
24
20
|
|
25
21
|
scope :search_import, -> { all }
|
26
22
|
|
@@ -31,27 +27,26 @@ module RediSearch
|
|
31
27
|
|
32
28
|
private
|
33
29
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
after_destroy_commit(:redi_search_delete_document) if
|
30
|
+
def register_search_commit_hooks
|
31
|
+
after_save_commit(:add_to_index) if respond_to?(:after_save_commit)
|
32
|
+
after_destroy_commit(:remove_from_index) if
|
38
33
|
respond_to?(:after_destroy_commit)
|
39
34
|
end
|
40
35
|
end
|
41
36
|
|
42
37
|
module ModelClassMethods
|
43
38
|
def search(term = nil, **term_options)
|
44
|
-
|
39
|
+
search_index.search(term, **term_options)
|
45
40
|
end
|
46
41
|
|
47
42
|
def spellcheck(term, distance: 1)
|
48
|
-
|
43
|
+
search_index.spellcheck(term, distance: distance)
|
49
44
|
end
|
50
45
|
|
51
46
|
def reindex(recreate: false, only: [])
|
52
47
|
search_import.find_in_batches.all? do |group|
|
53
|
-
|
54
|
-
group.map { |record| record.
|
48
|
+
search_index.reindex(
|
49
|
+
group.map { |record| record.search_document(only: only) },
|
55
50
|
recreate: recreate
|
56
51
|
)
|
57
52
|
end
|
@@ -59,19 +54,16 @@ module RediSearch
|
|
59
54
|
end
|
60
55
|
|
61
56
|
module InstanceMethods
|
62
|
-
def
|
63
|
-
Document.for_object(
|
64
|
-
self.class.redi_search_index, self,
|
65
|
-
only: only, serializer: self.class.redi_search_serializer
|
66
|
-
)
|
57
|
+
def search_document(only: [])
|
58
|
+
Document.for_object(self.class.search_index, self, only: only)
|
67
59
|
end
|
68
60
|
|
69
|
-
def
|
70
|
-
self.class.
|
61
|
+
def remove_from_index
|
62
|
+
self.class.search_index.del(search_document)
|
71
63
|
end
|
72
64
|
|
73
|
-
def
|
74
|
-
self.class.
|
65
|
+
def add_to_index
|
66
|
+
self.class.search_index.add(search_document)
|
75
67
|
end
|
76
68
|
end
|
77
69
|
end
|
@@ -3,17 +3,39 @@
|
|
3
3
|
module RediSearch
|
4
4
|
class Schema
|
5
5
|
class Field
|
6
|
+
def name
|
7
|
+
@name&.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
def coerce(value)
|
11
|
+
value
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize(record)
|
15
|
+
if value_block
|
16
|
+
record.instance_exec(&value_block)
|
17
|
+
else
|
18
|
+
record.public_send(name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
6
26
|
private
|
7
27
|
|
28
|
+
attr_reader :value_block
|
29
|
+
|
8
30
|
FALSES = [
|
9
31
|
nil, "", false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"
|
10
32
|
].freeze
|
11
33
|
|
12
34
|
def boolean_options_string
|
13
|
-
boolean_options.
|
35
|
+
boolean_options.filter_map do |option|
|
14
36
|
option.to_s.upcase.split("_").join unless
|
15
37
|
FALSES.include?(send(option))
|
16
|
-
end
|
38
|
+
end
|
17
39
|
end
|
18
40
|
end
|
19
41
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/schema/field"
|
4
|
-
|
5
3
|
module RediSearch
|
6
4
|
class Schema
|
7
5
|
class GeoField < Field
|
8
|
-
def initialize(name, sortable: false, no_index: false)
|
9
|
-
@name
|
10
|
-
@sortable
|
11
|
-
@no_index
|
6
|
+
def initialize(name, sortable: false, no_index: false, &block)
|
7
|
+
@name = name
|
8
|
+
@sortable = sortable
|
9
|
+
@no_index = no_index
|
10
|
+
@value_block = block
|
12
11
|
end
|
13
12
|
|
14
13
|
def to_a
|
@@ -20,7 +19,7 @@ module RediSearch
|
|
20
19
|
|
21
20
|
private
|
22
21
|
|
23
|
-
attr_reader :
|
22
|
+
attr_reader :sortable, :no_index
|
24
23
|
|
25
24
|
def boolean_options
|
26
25
|
%i(sortable no_index)
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/schema/field"
|
4
|
-
|
5
3
|
module RediSearch
|
6
4
|
class Schema
|
7
5
|
class NumericField < Field
|
8
|
-
def initialize(name, sortable: false, no_index: false)
|
9
|
-
@name
|
10
|
-
@sortable
|
11
|
-
@no_index
|
6
|
+
def initialize(name, sortable: false, no_index: false, &block)
|
7
|
+
@name = name
|
8
|
+
@sortable = sortable
|
9
|
+
@no_index = no_index
|
10
|
+
@value_block = block
|
12
11
|
end
|
13
12
|
|
14
13
|
def to_a
|
@@ -20,7 +19,7 @@ module RediSearch
|
|
20
19
|
|
21
20
|
private
|
22
21
|
|
23
|
-
attr_reader :
|
22
|
+
attr_reader :sortable, :no_index
|
24
23
|
|
25
24
|
def boolean_options
|
26
25
|
%i(sortable no_index)
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/schema/field"
|
4
|
-
|
5
3
|
module RediSearch
|
6
4
|
class Schema
|
7
5
|
class TagField < Field
|
8
|
-
def initialize(name, separator: ",", sortable: false, no_index: false
|
9
|
-
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
6
|
+
def initialize(name, separator: ",", sortable: false, no_index: false,
|
7
|
+
&block)
|
8
|
+
@name = name
|
9
|
+
@separator = separator
|
10
|
+
@sortable = sortable
|
11
|
+
@no_index = no_index
|
12
|
+
@value_block = block
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_a
|
@@ -20,9 +20,17 @@ module RediSearch
|
|
20
20
|
query
|
21
21
|
end
|
22
22
|
|
23
|
+
def coerce(value)
|
24
|
+
value.join(separator)
|
25
|
+
end
|
26
|
+
|
27
|
+
def tag?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
23
31
|
private
|
24
32
|
|
25
|
-
attr_reader :
|
33
|
+
attr_reader :separator, :sortable, :no_index
|
26
34
|
|
27
35
|
def boolean_options
|
28
36
|
%i(sortable no_index)
|
@@ -4,13 +4,14 @@ module RediSearch
|
|
4
4
|
class Schema
|
5
5
|
class TextField < Field
|
6
6
|
def initialize(name, weight: 1.0, phonetic: nil, sortable: false,
|
7
|
-
no_index: false, no_stem: false)
|
7
|
+
no_index: false, no_stem: false, &block)
|
8
8
|
@name = name
|
9
|
-
@
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
@value_block = block
|
10
|
+
|
11
|
+
{ weight: weight, phonetic: phonetic, sortable: sortable,
|
12
|
+
no_index: no_index, no_stem: no_stem }.each do |attr, value|
|
13
|
+
instance_variable_set("@#{attr}", value)
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
17
|
def to_a
|
@@ -24,7 +25,7 @@ module RediSearch
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
|
-
attr_reader :
|
28
|
+
attr_reader :weight, :phonetic, :sortable, :no_index, :no_stem
|
28
29
|
|
29
30
|
def boolean_options
|
30
31
|
%i(sortable no_index no_stem)
|
data/lib/redi_search/schema.rb
CHANGED
@@ -1,41 +1,54 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/schema/geo_field"
|
4
|
-
require "redi_search/schema/numeric_field"
|
5
|
-
require "redi_search/schema/tag_field"
|
6
|
-
require "redi_search/schema/text_field"
|
7
|
-
|
8
3
|
module RediSearch
|
9
4
|
class Schema
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
attr_reader :fields
|
6
|
+
|
7
|
+
def initialize(&block)
|
8
|
+
@fields = []
|
13
9
|
|
14
|
-
|
15
|
-
new(field_name, **options.to_h).to_a
|
10
|
+
instance_exec(&block)
|
16
11
|
end
|
17
12
|
|
18
|
-
def
|
19
|
-
|
13
|
+
def text_field(name, **options, &block)
|
14
|
+
self[name] || push(Schema::TextField.new(name, **options, &block))
|
20
15
|
end
|
21
16
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
def numeric_field(name, **options, &block)
|
18
|
+
self[name] || push(Schema::NumericField.new(name, **options, &block))
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_field(name, **options, &block)
|
22
|
+
self[name] || push(Schema::TagField.new(name, **options, &block))
|
23
|
+
end
|
24
|
+
|
25
|
+
def geo_field(name, **options, &block)
|
26
|
+
self[name] || push(Schema::GeoField.new(name, **options, &block))
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_field(name, type, **options, &block)
|
30
|
+
case type
|
31
|
+
when :text then method(:text_field)
|
32
|
+
when :numeric then method(:numeric_field)
|
33
|
+
when :tag then method(:tag_field)
|
34
|
+
when :geo then method(:geo_field)
|
35
|
+
end.call(name, **options, &block)
|
26
36
|
end
|
27
37
|
|
28
|
-
def
|
29
|
-
|
38
|
+
def to_a
|
39
|
+
fields.map(&:to_a).flatten
|
30
40
|
end
|
31
41
|
|
32
|
-
def
|
33
|
-
|
34
|
-
self
|
42
|
+
def [](name)
|
43
|
+
fields.find { |field| field.name == name }
|
35
44
|
end
|
36
45
|
|
37
46
|
private
|
38
47
|
|
39
|
-
|
48
|
+
def push(field)
|
49
|
+
@fields.push(field)
|
50
|
+
|
51
|
+
field
|
52
|
+
end
|
40
53
|
end
|
41
54
|
end
|
@@ -1,21 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "redi_search/search/term"
|
4
|
-
require "redi_search/search/clauses/slop"
|
5
|
-
require "redi_search/search/clauses/in_order"
|
6
|
-
require "redi_search/search/clauses/language"
|
7
|
-
require "redi_search/search/clauses/sort_by"
|
8
|
-
require "redi_search/search/clauses/limit"
|
9
|
-
require "redi_search/search/clauses/no_content"
|
10
|
-
require "redi_search/search/clauses/verbatim"
|
11
|
-
require "redi_search/search/clauses/no_stop_words"
|
12
|
-
require "redi_search/search/clauses/return"
|
13
|
-
require "redi_search/search/clauses/with_scores"
|
14
|
-
require "redi_search/search/clauses/highlight"
|
15
|
-
require "redi_search/search/clauses/and"
|
16
|
-
require "redi_search/search/clauses/or"
|
17
|
-
require "redi_search/search/clauses/where"
|
18
|
-
|
19
3
|
module RediSearch
|
20
4
|
class Search
|
21
5
|
module Clauses
|