redi_search 6.3.0 → 7.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +3 -3
  3. data/.github/workflows/tests.yml +6 -6
  4. data/.rubocop.yml +1 -1
  5. data/.ruby-version +1 -1
  6. data/Appraisals +5 -5
  7. data/Gemfile +4 -1
  8. data/gemfiles/{activerecord_60.gemfile → activerecord_71.gemfile} +1 -1
  9. data/lib/redi_search/aggregate/clauses/apply.rb +24 -0
  10. data/lib/redi_search/aggregate/clauses/filter.rb +22 -0
  11. data/lib/redi_search/aggregate/clauses/group_by.rb +79 -0
  12. data/lib/redi_search/aggregate/clauses/limit.rb +28 -0
  13. data/lib/redi_search/aggregate/clauses/load.rb +22 -0
  14. data/lib/redi_search/aggregate/clauses/sort_by.rb +43 -0
  15. data/lib/redi_search/aggregate/clauses/verbatim.rb +17 -0
  16. data/lib/redi_search/aggregate/reducers/average.rb +26 -0
  17. data/lib/redi_search/aggregate/reducers/count.rb +23 -0
  18. data/lib/redi_search/aggregate/reducers/distinct_count.rb +26 -0
  19. data/lib/redi_search/aggregate/reducers/distinctish_count.rb +26 -0
  20. data/lib/redi_search/aggregate/reducers/max.rb +26 -0
  21. data/lib/redi_search/aggregate/reducers/min.rb +26 -0
  22. data/lib/redi_search/aggregate/reducers/quantile.rb +30 -0
  23. data/lib/redi_search/aggregate/reducers/stdev.rb +26 -0
  24. data/lib/redi_search/aggregate/reducers/sum.rb +26 -0
  25. data/lib/redi_search/aggregate/reducers/to_list.rb +26 -0
  26. data/lib/redi_search/aggregate.rb +104 -0
  27. data/lib/redi_search/application_clause.rb +37 -0
  28. data/lib/redi_search/client.rb +5 -4
  29. data/lib/redi_search/index.rb +6 -0
  30. data/lib/redi_search/log_subscriber.rb +8 -3
  31. data/lib/redi_search/model.rb +5 -1
  32. data/lib/redi_search/schema/tag_field.rb +8 -0
  33. data/lib/redi_search/schema.rb +10 -10
  34. data/lib/redi_search/search/clauses/highlight.rb +3 -1
  35. data/lib/redi_search/search/clauses/in_order.rb +2 -0
  36. data/lib/redi_search/search/clauses/language.rb +1 -0
  37. data/lib/redi_search/search/clauses/limit.rb +1 -0
  38. data/lib/redi_search/search/clauses/no_content.rb +2 -0
  39. data/lib/redi_search/search/clauses/no_stop_words.rb +2 -0
  40. data/lib/redi_search/search/clauses/return.rb +1 -0
  41. data/lib/redi_search/search/clauses/slop.rb +1 -0
  42. data/lib/redi_search/search/clauses/sort_by.rb +1 -0
  43. data/lib/redi_search/search/clauses/timeout.rb +24 -0
  44. data/lib/redi_search/search/clauses/verbatim.rb +2 -0
  45. data/lib/redi_search/search/clauses/with_payloads.rb +17 -0
  46. data/lib/redi_search/search/clauses/with_scores.rb +2 -0
  47. data/lib/redi_search/search/clauses/with_sort_keys.rb +17 -0
  48. data/lib/redi_search/search/clauses.rb +36 -55
  49. data/lib/redi_search/search/{clauses → queries}/and.rb +1 -1
  50. data/lib/redi_search/search/{clauses → queries}/boolean.rb +4 -4
  51. data/lib/redi_search/search/{clauses → queries}/or.rb +1 -1
  52. data/lib/redi_search/search/{clauses → queries}/where.rb +2 -2
  53. data/lib/redi_search/search/queries.rb +39 -0
  54. data/lib/redi_search/search.rb +7 -6
  55. data/lib/redi_search/version.rb +1 -1
  56. data/redi_search.gemspec +2 -6
  57. metadata +34 -60
  58. data/lib/redi_search/search/clauses/application_clause.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d005b7e0b289004277bf5526a4270aa7dd707df16520ae0e2b9df577b12601c2
4
- data.tar.gz: 9b3954997aa84e9e25037c6b332c00139d7d112dad9fffbbe32281f9da0fdfe1
3
+ metadata.gz: faa46eaff63a1c9a9f0cdc17773a40130973dd995155239ce2c9c6e87c6418e4
4
+ data.tar.gz: ff20e1f29a52ed43cf820f1fe9d95268ccae19f414861ad8082c6fadbd9382db
5
5
  SHA512:
6
- metadata.gz: dfcbe3552fef2dcb9abda2ad3e51c2bf35a2d2a16a631f249d1f1a89e5ed3aab5f0815387ab5a472f13db9c1d8a430f114840e81147e2b44160b1890be0f6c94
7
- data.tar.gz: 3e2c1b66bb0053f42d886ab765468a213ab576b31d7d95a08f8bd216dcb8a933abbd76670207b2c9b366e988622a0aa1ece981901bb368916087c85a75b0726f
6
+ metadata.gz: '0293276b8df50570c9181419e8e91c6c710b5fdf4ec24ce64f218d5c3fdd47934c7a6885783096962ee459cd9c5a831bd1b81e1d88ba01bed58a2288d0155713'
7
+ data.tar.gz: 51859dbf694e71bab98895e4ff8400a76312e6c2e647f7fa0cef74cf87dde90d0974e943296531c6de44b4ce658114f2fd83b6e4fc48c55147b50563f6e52688
@@ -10,11 +10,11 @@ jobs:
10
10
  lint:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v2
14
- - name: Set up Ruby 3.1
13
+ - uses: actions/checkout@v4
14
+ - name: Set up Ruby 3.2
15
15
  uses: ruby/setup-ruby@v1
16
16
  with:
17
- ruby-version: 3.1
17
+ ruby-version: 3.2
18
18
  - name: Install rubocop
19
19
  run: |
20
20
  gem install rubocop rubocop-performance rubocop-minitest rubocop-rake
@@ -11,10 +11,10 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby: [ '2.7', '3.0', '3.1' ]
15
- gemfile: [ 'Gemfile', 'gemfiles/activerecord_60.gemfile', 'gemfiles/activerecord_61.gemfile', 'gemfiles/activerecord_70.gemfile' ]
14
+ ruby: [ '3.0', '3.1', '3.2' ]
15
+ gemfile: [ 'Gemfile', 'gemfiles/activerecord_61.gemfile', 'gemfiles/activerecord_70.gemfile', 'gemfiles/activerecord_71.gemfile' ]
16
16
  steps:
17
- - uses: actions/checkout@v2
17
+ - uses: actions/checkout@v4
18
18
  - name: Set up Ruby ${{ matrix.ruby }}
19
19
  uses: ruby/setup-ruby@v1
20
20
  with:
@@ -38,11 +38,11 @@ jobs:
38
38
  ports:
39
39
  - 6379:6379
40
40
  steps:
41
- - uses: actions/checkout@v2
42
- - name: Set up Ruby 3.1
41
+ - uses: actions/checkout@v4
42
+ - name: Set up Ruby 3.2
43
43
  uses: ruby/setup-ruby@v1
44
44
  with:
45
- ruby-version: 3.1
45
+ ruby-version: 3.2
46
46
  - name: Install dependencies
47
47
  run: |
48
48
  sudo apt-get install libsqlite3-dev -y
data/.rubocop.yml CHANGED
@@ -13,7 +13,7 @@ AllCops:
13
13
  - test/dummy/db/schema.rb
14
14
  - gemfiles/**/*
15
15
  - bin/**/*
16
- TargetRubyVersion: 2.7
16
+ TargetRubyVersion: 3.0
17
17
 
18
18
  # Department Bundler
19
19
  Bundler/DuplicatedGem:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.0-preview3
1
+ 3.2.2
data/Appraisals CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- appraise "activerecord-60" do
4
- gem "activerecord", "< 6.1", ">= 6.0"
5
- end
6
-
7
3
  appraise "activerecord-61" do
8
4
  gem "activerecord", "< 6.2", ">= 6.1"
9
5
  end
10
6
 
11
7
  appraise "activerecord-70" do
12
- gem "activerecord", "~> 7.0.0.alpha1"
8
+ gem "activerecord", "~> 7.0.0"
9
+ end
10
+
11
+ appraise "activerecord-70" do
12
+ gem "activerecord", "~> 7.1.0"
13
13
  end
data/Gemfile CHANGED
@@ -7,9 +7,12 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
7
7
  gemspec
8
8
 
9
9
  gem "appraisal", "~> 2.2"
10
+ gem "bundler", ">= 1.17", "< 3"
10
11
  gem "debug"
11
12
  gem "faker"
13
+ gem "minitest", "~> 5.0"
12
14
  gem "mocha"
15
+ gem "rake", "~> 13.0"
13
16
  gem "rubocop"
14
17
  gem "rubocop-minitest"
15
18
  gem "rubocop-performance"
@@ -17,4 +20,4 @@ gem "rubocop-rake"
17
20
  gem "simplecov"
18
21
  gem "sqlite3"
19
22
 
20
- gem "activerecord", "~> 7.0"
23
+ gem "activerecord", "~> 7.1"
@@ -11,6 +11,6 @@ gem "rubocop-minitest"
11
11
  gem "rubocop-performance"
12
12
  gem "simplecov"
13
13
  gem "sqlite3"
14
- gem "activerecord", "< 6.1", ">= 6.0"
14
+ gem "activerecord", "~> 7.1.0"
15
15
 
16
16
  gemspec path: "../"
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class Apply < ApplicationClause
7
+ clause_term :expression, presence: true
8
+ clause_term :as, presence: true
9
+ clause_order 5
10
+
11
+ def initialize(expression:, as:)
12
+ @expression = expression
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ ["APPLY", expression, "AS", as]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class Filter < ApplicationClause
7
+ clause_term :expression, presence: true
8
+ clause_order 6
9
+
10
+ def initialize(expression:)
11
+ @expression = expression
12
+ end
13
+
14
+ def clause
15
+ validate!
16
+
17
+ ["FILTER", expression]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class GroupBy < ApplicationClause
7
+ clause_term :fields, presence: true
8
+ clause_order 3
9
+
10
+ def initialize(fields:)
11
+ @fields = fields.map(&:to_s).map do |field|
12
+ field.prepend("@") unless field.start_with?("@")
13
+ end
14
+ @reducer = nil
15
+ end
16
+
17
+ def clause
18
+ validate!
19
+
20
+ ["GROUPBY", fields.count, *fields, *reducer&.clause].compact
21
+ end
22
+
23
+ def count(as: nil)
24
+ self.reducer = Reducers::Count.new(as: as).tap(&:validate!)
25
+ end
26
+
27
+ def distinct_count(property:, as: nil)
28
+ self.reducer = Reducers::DistinctCount.
29
+ new(property: property, as: as).tap(&:validate!)
30
+ end
31
+
32
+ def distinctish_count(property:, as: nil)
33
+ self.reducer = Reducers::DistinctishCount.
34
+ new(property: property, as: as).tap(&:validate!)
35
+ end
36
+
37
+ def sum(property:, as: nil)
38
+ self.reducer = Reducers::Sum.
39
+ new(property: property, as: as).tap(&:validate!)
40
+ end
41
+
42
+ def min(property:, as: nil)
43
+ self.reducer = Reducers::Min.
44
+ new(property: property, as: as).tap(&:validate!)
45
+ end
46
+
47
+ def max(property:, as: nil)
48
+ self.reducer = Reducers::Max.
49
+ new(property: property, as: as).tap(&:validate!)
50
+ end
51
+
52
+ def average(property:, as: nil)
53
+ self.reducer = Reducers::Average.
54
+ new(property: property, as: as).tap(&:validate!)
55
+ end
56
+
57
+ def stdev(property:, as: nil)
58
+ self.reducer = Reducers::Stdev.
59
+ new(property: property, as: as).tap(&:validate!)
60
+ end
61
+
62
+ def quantile(property:, quantile:, as: nil)
63
+ self.reducer = Reducers::Quantile.new(
64
+ property: property, quantile: quantile, as: as
65
+ ).tap(&:validate!)
66
+ end
67
+
68
+ def to_list(property:, as: nil)
69
+ self.reducer = Reducers::ToList.
70
+ new(property: property, as: as).tap(&:validate!)
71
+ end
72
+
73
+ private
74
+
75
+ attr_accessor :reducer
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class Limit < ApplicationClause
7
+ clause_term :total, presence: true, numericality: {
8
+ within: 0..Float::INFINITY, only_integer: true
9
+ }
10
+ clause_term :offset, presence: true, numericality: {
11
+ within: 0..Float::INFINITY, only_integer: true
12
+ }
13
+ clause_order 7
14
+
15
+ def initialize(total:, offset: 0)
16
+ @total = total
17
+ @offset = offset
18
+ end
19
+
20
+ def clause
21
+ validate!
22
+
23
+ ["LIMIT", offset, total]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class Load < ApplicationClause
7
+ clause_term :fields, presence: true
8
+ clause_order 2
9
+
10
+ def initialize(fields:)
11
+ @fields = fields
12
+ end
13
+
14
+ def clause
15
+ validate!
16
+
17
+ ["LOAD", fields.size, *fields]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class SortBy < ApplicationClause
7
+ class Sortable < ApplicationClause
8
+ clause_term :field, presence: true
9
+ clause_term :order, presence: true,
10
+ inclusion: { within: %i(asc desc) }
11
+
12
+ def initialize(field, order = :asc)
13
+ @field = field.to_s
14
+ @field.prepend("@") unless @field.start_with?("@")
15
+ @order = order.to_sym
16
+ end
17
+
18
+ def clause
19
+ [field, order.to_s.upcase]
20
+ end
21
+ end
22
+
23
+ clause_term :fields, presence: true
24
+ clause_order 4
25
+
26
+ def initialize(fields:)
27
+ @fields = fields.flat_map do |field|
28
+ if field.is_a?(Hash) then field.map { |k, v| Sortable.new(k, v) }
29
+ else
30
+ Sortable.new(field)
31
+ end
32
+ end
33
+ end
34
+
35
+ def clause
36
+ validate! && fields.each(&:validate!)
37
+
38
+ ["SORTBY", fields.count * 2, *fields.flat_map(&:clause)]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Clauses
6
+ class Verbatim < ApplicationClause
7
+ clause_order 1
8
+
9
+ def clause
10
+ validate!
11
+
12
+ ["VERBATIM"]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Average < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "AVG", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Count < ApplicationClause
7
+ clause_term :as
8
+
9
+ def initialize(as:)
10
+ @as = as
11
+ end
12
+
13
+ def clause
14
+ validate!
15
+
16
+ command = ["REDUCE", "COUNT", 0]
17
+ command += ["AS", as] if as
18
+ command
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class DistinctCount < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "COUNT_DISTINCT", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class DistinctishCount < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "COUNT_DISTINCTISH", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Max < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "MAX", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Min < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "MIN", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Quantile < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :quantile, presence: true, inclusion: {
9
+ within: 0.0..1.0
10
+ }
11
+ clause_term :as
12
+
13
+ def initialize(property:, quantile:, as:)
14
+ @property = property.to_s
15
+ @property.prepend("@") unless @property.start_with?("@")
16
+ @quantile = quantile
17
+ @as = as
18
+ end
19
+
20
+ def clause
21
+ validate!
22
+
23
+ command = ["REDUCE", "QUANTILE", 2, property, quantile]
24
+ command += ["AS", as] if as
25
+ command
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Stdev < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "STDEV", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class Sum < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "SUM", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RediSearch
4
+ class Aggregate
5
+ module Reducers
6
+ class ToList < ApplicationClause
7
+ clause_term :property, presence: true
8
+ clause_term :as
9
+
10
+ def initialize(property:, as:)
11
+ @property = property.to_s
12
+ @property.prepend("@") unless @property.start_with?("@")
13
+ @as = as
14
+ end
15
+
16
+ def clause
17
+ validate!
18
+
19
+ command = ["REDUCE", "TOLIST", 1, property]
20
+ command += ["AS", as] if as
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end