redi_search 6.3.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
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