123456789_123456789_123456789_123456789_123456789_

Class: Redis::Commands::Search::AggregateRequest

Relationships & Source Files
Inherits: Object
Defined in: lib/redis/commands/modules/search/aggregation.rb

Overview

A fluent builder for FT.AGGREGATE requests.

Aggregation steps (+group_by+, #sort_by, #apply, #filter, #limit, #load) are chained on; each returns self. #to_redis_args renders them into the argument array passed to FT.AGGREGATE, emitting LOAD steps before DIALECT and the remaining steps after it.

Examples:

req = Redis::Commands::Search::AggregateRequest.new("*")
  .group_by("@category", Redis::Commands::Search::Reducers.count(alias_name: "n"))

Class Method Summary

Instance Method Summary

Constructor Details

.new(query = "*", with_cursor: false, cursor_count: nil, cursor_max_idle: nil, dialect: DEFAULT_DIALECT) ⇒ AggregateRequest

Parameters:

  • query (String) (defaults to: "*")

    the aggregation query string (defaults to "*")

  • with_cursor (Boolean)

    emit WITHCURSOR to page results with a cursor

  • cursor_count (Integer, nil)

    the cursor COUNT (batch size)

  • cursor_max_idle (Integer, nil)

    the cursor MAXIDLE in milliseconds

  • dialect (Integer)

    the query DIALECT version (defaults to DEFAULT_DIALECT)

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 22

def initialize(query = "*", with_cursor: false, cursor_count: nil, cursor_max_idle: nil,
               dialect: DEFAULT_DIALECT)
  @query = query
  @with_cursor = with_cursor
  @cursor_count = cursor_count
  @cursor_max_idle = cursor_max_idle
  @dialect = dialect
  @steps = []
end

Instance Method Details

#add_scores(add_scores: true) ⇒ self

Include the document scores in the aggregation (+ADDSCORES+).

Parameters:

  • add_scores (Boolean)

    whether to emit ADDSCORES

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 120

def add_scores(add_scores: true)
  @add_scores = add_scores
  self
end

#apply(expressions) ⇒ self

Add one APPLY step per expression.

Parameters:

  • expressions (Hash{String, Symbol => String})

    map of result alias => expression

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 77

def apply(expressions)
  expressions.each do |as, expression|
    @steps << ["APPLY", expression, "AS", as.to_s]
  end
  self
end

#dialect(dialect_version) ⇒ self

Set the query DIALECT version.

Parameters:

  • dialect_version (Integer)

    the dialect version

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 129

def dialect(dialect_version)
  @dialect = dialect_version
  self
end

#filter(expression) ⇒ self

Add a FILTER step that keeps rows matching expression.

Parameters:

  • expression (String)

    the filter expression

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 98

def filter(expression)
  @steps << ["FILTER", expression]
  self
end

#group_by(fields, *reducers) ⇒ self

Add a GROUPBY step with optional REDUCE functions.

Parameters:

  • fields (String, Array<String>)

    the field(s) to group by

  • reducers (Array<Reducers>)

    the reducers applied to each group

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 37

def group_by(fields, *reducers)
  step = ["GROUPBY", Array(fields).size.to_s, *Array(fields)]
  reducers.each do |reducer|
    step.concat(["REDUCE", reducer.name, reducer.args.size.to_s])
    step.concat(reducer.args)
    step.concat(["AS", reducer.alias_name]) if reducer.alias_name
  end
  @steps << step.flatten
  self
end

#limit(offset, num) ⇒ self

Add a LIMIT (paging) step.

Parameters:

  • offset (Integer)

    the index of the first row to return

  • num (Integer)

    the maximum number of rows to return

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 89

def limit(offset, num)
  @steps << ["LIMIT", offset, num]
  self
end

#load(*fields) ⇒ self

Add a LOAD step. With no fields, loads all attributes (+LOAD *+).

Parameters:

  • fields (Array<String>)

    the fields to load (empty loads all)

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 107

def load(*fields)
  @steps << if fields.empty?
    ["LOAD", "*"]
  else
    ["LOAD", fields.size, *fields.flatten]
  end
  self
end

#sort_by(*sort_by_fields, max: nil) ⇒ self

Add a SORTBY step.

Parameters:

  • sort_by_fields (Array<Asc, Desc, String>)

    the fields to sort by; Asc+/+Desc wrappers carry an explicit direction, plain strings sort with the server default

  • max (Integer, nil)

    limit the sort to the top MAX results

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 54

def sort_by(*sort_by_fields, max: nil)
  # Count total arguments (field + order for each)
  nargs = sort_by_fields.sum do |field|
    field.is_a?(Asc) || field.is_a?(Desc) ? 2 : 1
  end

  step = ["SORTBY", nargs]
  sort_by_fields.each do |field|
    if field.is_a?(Asc) || field.is_a?(Desc)
      step << field.name << field.order
    else
      step << field
    end
  end
  step << "MAX" << max if max
  @steps << step
  self
end

#to_redis_argsArray

Render the request into the FT.AGGREGATE argument array.

LOAD steps are emitted before DIALECT and all other steps after it.

Returns:

  • (Array)

    the argument token array (query string first)

[ GitHub ]

  
# File 'lib/redis/commands/modules/search/aggregation.rb', line 139

def to_redis_args
  args = [@query]
  if @with_cursor
    args << "WITHCURSOR"
    args << "COUNT" << @cursor_count if @cursor_count
    args << "MAXIDLE" << @cursor_max_idle if @cursor_max_idle
  end
  args << "ADDSCORES" if @add_scores
  # Add LOAD steps first (before DIALECT)
  load_steps = @steps.select { |step| step[0] == "LOAD" }
  load_steps.each { |step| args.concat(step) }

  args << "DIALECT" << @dialect if @dialect

  # Add remaining steps (after DIALECT)
  other_steps = @steps.reject { |step| step[0] == "LOAD" }
  other_steps.each { |step| args.concat(step) }
  args
end