Class: ParadeDB::Arel::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/parade_db/arel/builder.rb

Constant Summary collapse

RANGE_TYPES =
%w[int4range int8range numrange daterange tsrange tstzrange].freeze
RANGE_RELATIONS =
%w[Intersects Contains Within].freeze
TOKENIZER_EXPRESSION =
/\A[a-zA-Z_][a-zA-Z0-9_]*(?:(?:::|\.)[a-zA-Z_][a-zA-Z0-9_]*)*(?:\(\s*[a-zA-Z0-9_'".,=\s:-]*\s*\))?\z/.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table = nil) ⇒ Builder

Returns a new instance of Builder.



14
15
16
# File 'lib/parade_db/arel/builder.rb', line 14

def initialize(table = nil)
  @table = table
end

Instance Attribute Details

#tableObject (readonly)

Returns the value of attribute table.



12
13
14
# File 'lib/parade_db/arel/builder.rb', line 12

def table
  @table
end

Instance Method Details

#[](column) ⇒ Object



18
19
20
# File 'lib/parade_db/arel/builder.rb', line 18

def [](column)
  column_node(column)
end

#agg(json, exact: nil) ⇒ Object



255
256
257
258
259
260
261
262
263
# File 'lib/parade_db/arel/builder.rb', line 255

def agg(json, exact: nil)
  unless exact.nil? || exact == true || exact == false
    raise ArgumentError, "exact must be true, false, or nil"
  end

  args = [quoted_value(json)]
  args << quoted_value(false) if exact == false
  ::Arel::Nodes::NamedFunction.new("pdb.agg", args)
end

#exists(column, boost: nil, constant_score: nil) ⇒ Object



188
189
190
191
192
# File 'lib/parade_db/arel/builder.rb', line 188

def exists(column, boost: nil, constant_score: nil)
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.exists", [])
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#full_text(column, expression) ⇒ Object



80
81
82
83
# File 'lib/parade_db/arel/builder.rb', line 80

def full_text(column, expression)
  rhs = expression.is_a?(::Arel::Nodes::Node) ? expression : ::Arel.sql(expression.to_s)
  infix("@@@", column_node(column), rhs)
end

#match(column, *terms, tokenizer: nil, distance: nil, prefix: nil, transposition_cost_one: nil, boost: nil, constant_score: nil) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/parade_db/arel/builder.rb', line 22

def match(
  column,
  *terms,
  tokenizer: nil,
  distance: nil,
  prefix: nil,
  transposition_cost_one: nil,
  boost: nil,
  constant_score: nil
)
  validate_tokenizer_fuzzy_compatibility!(
    tokenizer: tokenizer,
    distance: distance,
    prefix: prefix,
    transposition_cost_one: transposition_cost_one
  )
  rhs = quoted_value(join_terms(terms))
  rhs = apply_fuzzy(
    rhs,
    distance: distance,
    prefix: prefix,
    transposition_cost_one: transposition_cost_one,
    bridge_to_query: !constant_score.nil?
  )
  rhs = apply_tokenizer(rhs, tokenizer)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("&&&", column_node(column), rhs)
end

#match_all(column, boost: nil, constant_score: nil) ⇒ Object



182
183
184
185
186
# File 'lib/parade_db/arel/builder.rb', line 182

def match_all(column, boost: nil, constant_score: nil)
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.all", [])
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#match_any(column, *terms, tokenizer: nil, distance: nil, prefix: nil, transposition_cost_one: nil, boost: nil, constant_score: nil) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/parade_db/arel/builder.rb', line 51

def match_any(
  column,
  *terms,
  tokenizer: nil,
  distance: nil,
  prefix: nil,
  transposition_cost_one: nil,
  boost: nil,
  constant_score: nil
)
  validate_tokenizer_fuzzy_compatibility!(
    tokenizer: tokenizer,
    distance: distance,
    prefix: prefix,
    transposition_cost_one: transposition_cost_one
  )
  rhs = quoted_value(join_terms(terms))
  rhs = apply_fuzzy(
    rhs,
    distance: distance,
    prefix: prefix,
    transposition_cost_one: transposition_cost_one,
    bridge_to_query: !constant_score.nil?
  )
  rhs = apply_tokenizer(rhs, tokenizer)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("|||", column_node(column), rhs)
end

#more_like_this(column, key, fields: nil, options: {}, boost: nil, constant_score: nil) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/parade_db/arel/builder.rb', line 207

def more_like_this(column, key, fields: nil, options: {}, boost: nil, constant_score: nil)
  args = [quoted_value(key)]
  unless fields.nil?
    field_values = Array(fields).map { |field| quoted_value(field.to_s) }
    args << Nodes::ArrayLiteral.new(field_values)
  end

  options.each do |name, value|
    args << mlt_option_node(name, value)
  end

  rhs = ::Arel::Nodes::NamedFunction.new("pdb.more_like_this", args)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#near(column, proximity, boost: nil, const: nil) ⇒ Object



153
154
155
156
# File 'lib/parade_db/arel/builder.rb', line 153

def near(column, proximity, boost: nil, const: nil)
  rhs = proximity_query_node(proximity, boost: boost, const: const)
  infix("@@@", column_node(column), rhs)
end

#parse(column, query, lenient: nil, conjunction_mode: nil, boost: nil, constant_score: nil) ⇒ Object



172
173
174
175
176
177
178
179
180
# File 'lib/parade_db/arel/builder.rb', line 172

def parse(column, query, lenient: nil, conjunction_mode: nil, boost: nil, constant_score: nil)
  rhs = Nodes::ParseNode.new(
    quoted_value(query),
    lenient: lenient,
    conjunction_mode: conjunction_mode
  )
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#phrase(column, text, slop: nil, tokenizer: nil, boost: nil, constant_score: nil) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/parade_db/arel/builder.rb', line 85

def phrase(column, text, slop: nil, tokenizer: nil, boost: nil, constant_score: nil)
  rhs =
    if text.is_a?(::Array)
      raise ArgumentError, "tokenizer is not supported for pretokenized phrase arrays" unless tokenizer.nil?

      Nodes::ArrayLiteral.new(normalize_phrase_terms(text).map { |term| quoted_value(term) })
    else
      apply_tokenizer(quoted_value(text), tokenizer)
    end

  rhs = apply_slop(rhs, slop)
  # ParadeDB cannot cast pdb.slop directly to pdb.const. Bridge through pdb.query.
  rhs = Nodes::QueryCast.new(rhs) if !constant_score.nil? && !slop.nil?
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("###", column_node(column), rhs)
end

#phrase_prefix(column, *terms, max_expansion: nil, boost: nil, constant_score: nil) ⇒ Object

Raises:

  • (ArgumentError)


158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/parade_db/arel/builder.rb', line 158

def phrase_prefix(column, *terms, max_expansion: nil, boost: nil, constant_score: nil)
  flat = terms.flatten.compact
  raise ArgumentError, "phrase_prefix requires at least one term" if flat.empty?
  array = Nodes::ArrayLiteral.new(flat.map { |term| quoted_value(term) })
  args = [array]
  unless max_expansion.nil?
    validate_integer!(max_expansion, :max_expansion)
    args << quoted_value(max_expansion)
  end
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.phrase_prefix", args)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#range(column, value = nil, gte: nil, gt: nil, lte: nil, lt: nil, type: nil, boost: nil, constant_score: nil) ⇒ Object



194
195
196
197
198
199
# File 'lib/parade_db/arel/builder.rb', line 194

def range(column, value = nil, gte: nil, gt: nil, lte: nil, lt: nil, type: nil, boost: nil, constant_score: nil)
  range_node = build_range_node(value, gte: gte, gt: gt, lte: lte, lt: lt, type: type)
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.range", [range_node])
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#range_term(column, value, relation: nil, range_type: nil, boost: nil, constant_score: nil) ⇒ Object



201
202
203
204
205
# File 'lib/parade_db/arel/builder.rb', line 201

def range_term(column, value, relation: nil, range_type: nil, boost: nil, constant_score: nil)
  rhs = build_range_term_node(value, relation: relation, range_type: range_type)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#regex(column, pattern, boost: nil, constant_score: nil) ⇒ Object



131
132
133
134
135
# File 'lib/parade_db/arel/builder.rb', line 131

def regex(column, pattern, boost: nil, constant_score: nil)
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.regex", [quoted_value(pattern)])
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#regex_phrase(column, *patterns, slop: nil, max_expansions: nil, boost: nil, constant_score: nil) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/parade_db/arel/builder.rb', line 137

def regex_phrase(column, *patterns, slop: nil, max_expansions: nil, boost: nil, constant_score: nil)
  normalized_patterns = normalize_regex_patterns(patterns)
  args = [Nodes::ArrayLiteral.new(normalized_patterns.map { |pattern| quoted_value(pattern) })]
  unless slop.nil?
    validate_numeric!(slop, :slop)
    args << keyword_arg_node("slop", slop)
  end
  unless max_expansions.nil?
    validate_integer!(max_expansions, :max_expansions)
    args << keyword_arg_node("max_expansions", max_expansions)
  end
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.regex_phrase", args)
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end

#score(key) ⇒ Object



223
224
225
# File 'lib/parade_db/arel/builder.rb', line 223

def score(key)
  ::Arel::Nodes::NamedFunction.new("pdb.score", [column_node(key)])
end

#snippet(column, *args) ⇒ Object



227
228
229
230
# File 'lib/parade_db/arel/builder.rb', line 227

def snippet(column, *args)
  call_args = [column_node(column)] + args.map { |arg| quoted_value(arg) }
  ::Arel::Nodes::NamedFunction.new("pdb.snippet", call_args)
end

#snippet_positions(column) ⇒ Object



251
252
253
# File 'lib/parade_db/arel/builder.rb', line 251

def snippet_positions(column)
  ::Arel::Nodes::NamedFunction.new("pdb.snippet_positions", [column_node(column)])
end

#snippets(column, start_tag: nil, end_tag: nil, max_num_chars: nil, limit: nil, offset: nil, sort_by: nil) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/parade_db/arel/builder.rb', line 232

def snippets(
  column,
  start_tag: nil,
  end_tag: nil,
  max_num_chars: nil,
  limit: nil,
  offset: nil,
  sort_by: nil
)
  call_args = [column_node(column)]
  call_args << keyword_arg_node("start_tag", start_tag) unless start_tag.nil?
  call_args << keyword_arg_node("end_tag", end_tag) unless end_tag.nil?
  call_args << keyword_arg_node("max_num_chars", max_num_chars) unless max_num_chars.nil?
  call_args << keyword_arg_node("limit", limit, quoted_name: true) unless limit.nil?
  call_args << keyword_arg_node("offset", offset, quoted_name: true) unless offset.nil?
  call_args << keyword_arg_node("sort_by", sort_by) unless sort_by.nil?
  ::Arel::Nodes::NamedFunction.new("pdb.snippets", call_args)
end

#term(column, term, distance: nil, prefix: nil, transposition_cost_one: nil, boost: nil, constant_score: nil) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/parade_db/arel/builder.rb', line 102

def term(
  column,
  term,
  distance: nil,
  prefix: nil,
  transposition_cost_one: nil,
  boost: nil,
  constant_score: nil
)
  rhs = quoted_value(term)
  rhs = apply_fuzzy(
    rhs,
    distance: distance,
    prefix: prefix,
    transposition_cost_one: transposition_cost_one,
    bridge_to_query: !constant_score.nil?
  )
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("===", column_node(column), rhs)
end

#term_set(column, *terms, boost: nil, constant_score: nil) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/parade_db/arel/builder.rb', line 123

def term_set(column, *terms, boost: nil, constant_score: nil)
  normalized_terms = normalize_term_set_terms(terms)
  array = Nodes::ArrayLiteral.new(normalized_terms.map { |term| quoted_value(term) })
  rhs = ::Arel::Nodes::NamedFunction.new("pdb.term_set", [array])
  rhs = apply_score_modifier(rhs, boost: boost, constant_score: constant_score)
  infix("@@@", column_node(column), rhs)
end