Class: Queries::Query
- Inherits:
-
Object
show all
- Includes:
- Arel::Nodes, Concerns::Identifiers
- Defined in:
- lib/queries/query.rb
Direct Known Subclasses
BiologicalRelationship::Autocomplete, CommonName::Filter, Container::Autocomplete, ControlledVocabularyTerm::Autocomplete, Descriptor::Autocomplete, Document::Autocomplete, Georeference::Filter, Namespace::Autocomplete, ObservationMatrixRow::Autocomplete, Otu::Autocomplete, Otu::Filter, AssertedDistribution::Autocomplete, CollectingEvent::Autocomplete, CollectionObject::Autocomplete, CollectionObject::Filter, DataAttribute::Autocomplete, DataAttribute::ValueAutocomplete, GeographicArea::Autocomplete, Identifier::Autocomplete, Image::Autocomplete, Loan::Autocomplete, Note::Autocomplete, Organization::Autocomplete, OriginRelationship::Filter, Person::Autocomplete, Person::Filter, Serial::Autocomplete, Source::Autocomplete, Source::Filter, TaxonDetermination::Filter, TaxonName::Autocomplete, TaxonName::Filter, TaxonName::Tabular, TaxonNameRelationship::Filter, TaxonNameRelationshipsFilterQuery, TypeMaterialAutocompleteQuery, Repository::Autocomplete, User::Autocomplete
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#alphabetic_strings ⇒ Array
-
#attribute_exact_facet(attribute = nil) ⇒ Object
params attribute [Symbol] a facet for use when params include, `author`, and `exact_author` combinations See queries/source/filter.rb for example use.
-
#autocomplete ⇒ Array
Default the autocomplete result to all TODO: eliminate.
-
#autocomplete_cached ⇒ ActiveRecord::Relation
-
#autocomplete_cached_wildcard_anywhere ⇒ ActiveRecord::Relation
-
#autocomplete_common_name_exact ⇒ Object
-
#autocomplete_common_name_like ⇒ Object
-
#autocomplete_exact_id ⇒ ActiveRecord::Relation
-
#autocomplete_exactly_named ⇒ ActiveRecord::Relation
-
#autocomplete_named ⇒ ActiveRecord::Relation
-
#autocomplete_ordered_wildcard_pieces_in_cached ⇒ ActiveRecord::Relation
-
#build_terms ⇒ Array
Ultimately we should replace this concept with full text indexing.
-
#cached ⇒ ActiveRecord::Relation?
!!TODO: rename :cached_matches or similar (this is problematic !!).
-
#combine_or_clauses(clauses) ⇒ Arel::Nodes::Grouping
-
#common_name_name ⇒ Object
-
#common_name_table ⇒ Object
-
#common_name_wild_pieces ⇒ Object
-
#end_wildcard ⇒ String
-
#exactly_named ⇒ Arel::Nodes::Matches
-
#fragments ⇒ Array
Used in unordered AND searches.
-
#initialize(string, project_id: nil, **keyword_args) ⇒ Query
constructor
-
#integers ⇒ Array
Of strings representing integers.
-
#levenshtein_distance(attribute, value) ⇒ Object
-
#match_ordered_wildcard_pieces_in_cached ⇒ Arel::Nodes::Matches
-
#match_wildcard_end_in_cached ⇒ Arel::Nodes::Matches
match ALL wildcards, but unordered, if 2 - 6 pieces provided.
-
#match_wildcard_in_cached ⇒ Arel::Nodes::Matches
match ALL wildcards, but unordered, if 2 - 6 pieces provided.
-
#named ⇒ Arel::Nodes::Matches
-
#no_terms? ⇒ Boolean
-
#only_ids ⇒ Query?
Used in or_clauses, match on id only if integers alone provided.
-
#only_integers? ⇒ Boolean
-
#parent ⇒ Arel::Nodes::TableAlias
-
#parent_child_join ⇒ Scope
-
#parent_child_where ⇒ Arel::Nodes::Grouping
Match at two levels, for example, 'wa te“ will match ”Washington Co., Texas“.
-
#pieces ⇒ Array
-
#result ⇒ Array
TODO: deprecate? probably unused.
-
#scope ⇒ Scope
stub TODO: deprecate? probably unused.
-
#start_and_end_wildcard ⇒ String
-
#start_wildcard ⇒ String
-
#wildcard_pieces ⇒ String
If `foo, and 123 and stuff` then %foo%and%123%and%stuff%.
-
#wildcard_wrapped_integers ⇒ Array
-
#wildcard_wrapped_years ⇒ Array
-
#with_cached ⇒ Arel::Nodes::Matches
-
#with_cached_like ⇒ Arel::Nodes::Matches
-
#with_id ⇒ Query?
-
#with_project_id ⇒ Arel::Nodes::Equality
TODO: nil/or clause this.
-
#year_letter ⇒ String?
-
#years ⇒ Array
Constructor Details
#initialize(string, project_id: nil, **keyword_args) ⇒ Query
Returns a new instance of Query.
35
36
37
38
39
40
|
# File 'lib/queries/query.rb', line 35
def initialize(string, project_id: nil, **keyword_args)
@query_string = string
@options = keyword_args
@project_id = project_id
build_terms
end
|
Instance Attribute Details
#dynamic_limit ⇒ Integer
32
33
34
|
# File 'lib/queries/query.rb', line 32
def dynamic_limit
@dynamic_limit
end
|
#options ⇒ Object
parameters from keyword_args, used to group and pass along things like annotator params
29
30
31
|
# File 'lib/queries/query.rb', line 29
def options
@options
end
|
#project_id ⇒ Object
Returns the value of attribute project_id.
26
27
28
|
# File 'lib/queries/query.rb', line 26
def project_id
@project_id
end
|
#query_string ⇒ String?
Returns the initial, unparsed value.
23
24
25
|
# File 'lib/queries/query.rb', line 23
def query_string
@query_string
end
|
#terms ⇒ Array
64
65
66
|
# File 'lib/queries/query.rb', line 64
def terms
@terms
end
|
Instance Method Details
#alphabetic_strings ⇒ Array
#attribute_exact_facet(attribute = nil) ⇒ Object
params attribute [Symbol]
a facet for use when params include, `author`, and `exact_author` combinations
See queries/source/filter.rb for example use
176
177
178
179
180
181
182
183
184
|
# File 'lib/queries/query.rb', line 176
def attribute_exact_facet(attribute = nil)
a = attribute.to_sym
return nil if send(a).blank?
if send("exact_#{a}".to_sym)
table[a].eq(send(a).strip)
else
table[a].matches('%' + send(a).strip.gsub(/\s+/, '%') + '%')
end
end
|
#autocomplete ⇒ Array
Returns default the autocomplete result to all TODO: eliminate.
306
307
308
|
# File 'lib/queries/query.rb', line 306
def autocomplete
all.to_a
end
|
#autocomplete_cached ⇒ ActiveRecord::Relation
331
332
333
334
335
336
337
|
# File 'lib/queries/query.rb', line 331
def autocomplete_cached
if a = cached
base_query.where(a.to_sql).limit(20)
else
nil
end
end
|
#autocomplete_cached_wildcard_anywhere ⇒ ActiveRecord::Relation
Returns removes years/integers!.
324
325
326
327
328
|
# File 'lib/queries/query.rb', line 324
def autocomplete_cached_wildcard_anywhere
a = match_wildcard_in_cached
return nil if a.nil?
base_query.where(a.to_sql).limit(20)
end
|
#autocomplete_common_name_exact ⇒ Object
363
364
365
366
|
# File 'lib/queries/query.rb', line 363
def autocomplete_common_name_exact
return nil if no_terms?
query_base.joins(:common_names).where(common_name_name.to_sql).limit(1)
end
|
#autocomplete_common_name_like ⇒ Object
368
369
370
371
|
# File 'lib/queries/query.rb', line 368
def autocomplete_common_name_like
return nil if no_terms?
query_base.joins(:common_names).where(common_name_wild_pieces.to_sql).limit(5)
end
|
#autocomplete_exact_id ⇒ ActiveRecord::Relation
311
312
313
314
|
# File 'lib/queries/query.rb', line 311
def autocomplete_exact_id
return nil if no_terms?
base_query.where(id: query_string).limit(1)
end
|
#autocomplete_exactly_named ⇒ ActiveRecord::Relation
340
341
342
343
|
# File 'lib/queries/query.rb', line 340
def autocomplete_exactly_named
return nil if no_terms?
base_query.where(exactly_named.to_sql).limit(20)
end
|
#autocomplete_named ⇒ ActiveRecord::Relation
346
347
348
349
|
# File 'lib/queries/query.rb', line 346
def autocomplete_named
return nil if no_terms?
base_query.where(named.to_sql).limit(5)
end
|
#autocomplete_ordered_wildcard_pieces_in_cached ⇒ ActiveRecord::Relation
317
318
319
320
|
# File 'lib/queries/query.rb', line 317
def autocomplete_ordered_wildcard_pieces_in_cached
return nil if no_terms?
base_query.where(match_ordered_wildcard_pieces_in_cached.to_sql).limit(5)
end
|
#build_terms ⇒ Array
Ultimately we should replace this concept with full text indexing.
78
79
80
|
# File 'lib/queries/query.rb', line 78
def build_terms
@terms = @query_string.blank? ? [] : [end_wildcard, start_and_end_wildcard]
end
|
#cached ⇒ ActiveRecord::Relation?
!!TODO: rename :cached_matches or similar (this is problematic !!)
247
248
249
250
|
# File 'lib/queries/query.rb', line 247
def cached
return nil if no_terms?
(table[:cached].matches_any(terms)).or(match_ordered_wildcard_pieces_in_cached)
end
|
#combine_or_clauses(clauses) ⇒ Arel::Nodes::Grouping
282
283
284
285
286
287
288
289
290
|
# File 'lib/queries/query.rb', line 282
def combine_or_clauses(clauses)
clauses.compact!
raise TaxonWorks::Error, 'combine_or_clauses called without a clause, ensure at least one exists' unless !clauses.empty?
a = clauses.shift
clauses.each do |b|
a = a.or(b)
end
a
end
|
#common_name_name ⇒ Object
355
356
357
|
# File 'lib/queries/query.rb', line 355
def common_name_name
common_name_table[:name].eq(query_string)
end
|
#common_name_table ⇒ Object
351
352
353
|
# File 'lib/queries/query.rb', line 351
def common_name_table
::CommonName.arel_table
end
|
#common_name_wild_pieces ⇒ Object
359
360
361
|
# File 'lib/queries/query.rb', line 359
def common_name_wild_pieces
common_name_table[:name].matches(wildcard_pieces)
end
|
#end_wildcard ⇒ String
88
89
90
|
# File 'lib/queries/query.rb', line 88
def end_wildcard
query_string + '%'
end
|
#exactly_named ⇒ Arel::Nodes::Matches
225
226
227
|
# File 'lib/queries/query.rb', line 225
def exactly_named
table[:name].eq(query_string) if !query_string.blank?
end
|
#fragments ⇒ Array
Used in unordered AND searches
126
127
128
129
130
131
132
133
|
# File 'lib/queries/query.rb', line 126
def fragments
a = alphabetic_strings
if a.size > 0 && a.size < 6
a.collect{|a| "%#{a}%"}
else
[]
end
end
|
#integers ⇒ Array
Returns of strings representing integers.
#levenshtein_distance(attribute, value) ⇒ Object
292
293
294
295
296
|
# File 'lib/queries/query.rb', line 292
def levenshtein_distance(attribute, value)
value = "'" + value.gsub(/'/, "''") + "'"
a = ApplicationRecord.sanitize_sql(value)
Arel::Nodes::NamedFunction.new("levenshtein", [table[attribute], Arel::Nodes::SqlLiteral.new(a) ] )
end
|
#match_ordered_wildcard_pieces_in_cached ⇒ Arel::Nodes::Matches
263
264
265
|
# File 'lib/queries/query.rb', line 263
def match_ordered_wildcard_pieces_in_cached
table[:cached].matches(wildcard_pieces)
end
|
#match_wildcard_end_in_cached ⇒ Arel::Nodes::Matches
match ALL wildcards, but unordered, if 2 - 6 pieces provided
269
270
271
|
# File 'lib/queries/query.rb', line 269
def match_wildcard_end_in_cached
table[:cached].matches(end_wildcard)
end
|
#match_wildcard_in_cached ⇒ Arel::Nodes::Matches
match ALL wildcards, but unordered, if 2 - 6 pieces provided
275
276
277
278
279
|
# File 'lib/queries/query.rb', line 275
def match_wildcard_in_cached
b = fragments
return nil if b.empty?
table[:cached].matches_all(b)
end
|
#named ⇒ Arel::Nodes::Matches
220
221
222
|
# File 'lib/queries/query.rb', line 220
def named
table[:name].matches_any(terms) if terms.any?
end
|
#no_terms? ⇒ Boolean
71
72
73
|
# File 'lib/queries/query.rb', line 71
def no_terms?
terms.none?
end
|
#only_ids ⇒ Query?
Returns used in or_clauses, match on id only if integers alone provided.
211
212
213
214
215
216
217
|
# File 'lib/queries/query.rb', line 211
def only_ids
if only_integers?
with_id
else
nil
end
end
|
#only_integers? ⇒ Boolean
#parent ⇒ Arel::Nodes::TableAlias
230
231
232
|
# File 'lib/queries/query.rb', line 230
def parent
table.alias
end
|
#parent_child_join ⇒ Scope
187
188
189
|
# File 'lib/queries/query.rb', line 187
def parent_child_join
table.join(parent).on(table[:parent_id].eq(parent[:id])).join_sources end
|
#parent_child_where ⇒ Arel::Nodes::Grouping
Match at two levels, for example, 'wa te“ will match ”Washington Co., Texas“
193
194
195
196
197
|
# File 'lib/queries/query.rb', line 193
def parent_child_where
a,b = query_string.split(/\s+/, 2)
return table[:id].eq(-1) if a.nil? || b.nil?
table[:name].matches("#{a}%").and(parent[:name].matches("#{b}%"))
end
|
#pieces ⇒ Array
138
139
140
|
# File 'lib/queries/query.rb', line 138
def pieces
query_string.split(/\s+/)
end
|
#result ⇒ Array
TODO: deprecate? probably unused
45
46
47
|
# File 'lib/queries/query.rb', line 45
def result
[]
end
|
#scope ⇒ Scope
stub TODO: deprecate? probably unused
52
53
54
|
# File 'lib/queries/query.rb', line 52
def scope
where('1 = 2')
end
|
#start_and_end_wildcard ⇒ String
93
94
95
|
# File 'lib/queries/query.rb', line 93
def start_and_end_wildcard
'%' + query_string + '%'
end
|
#start_wildcard ⇒ String
83
84
85
|
# File 'lib/queries/query.rb', line 83
def start_wildcard
'%' + query_string
end
|
#wildcard_pieces ⇒ String
Returns if `foo, and 123 and stuff` then %foo%and%123%and%stuff%.
154
155
156
|
# File 'lib/queries/query.rb', line 154
def wildcard_pieces
'%' + query_string.gsub(/[\W]+/, '%') + '%'
end
|
#wildcard_wrapped_integers ⇒ Array
143
144
145
|
# File 'lib/queries/query.rb', line 143
def wildcard_wrapped_integers
integers.collect{|i| "%#{i}%"}
end
|
#wildcard_wrapped_years ⇒ Array
148
149
150
|
# File 'lib/queries/query.rb', line 148
def wildcard_wrapped_years
years.collect{|i| "%#{i}%"}
end
|
#with_cached ⇒ Arel::Nodes::Matches
253
254
255
|
# File 'lib/queries/query.rb', line 253
def with_cached
table[:cached].eq(query_string)
end
|
#with_cached_like ⇒ Arel::Nodes::Matches
258
259
260
|
# File 'lib/queries/query.rb', line 258
def with_cached_like
table[:cached].matches(start_and_end_wildcard)
end
|
#with_id ⇒ Query?
Returns used in or_clauses.
201
202
203
204
205
206
207
|
# File 'lib/queries/query.rb', line 201
def with_id
if integers.any?
table[:id].eq_any(integers)
else
nil
end
end
|
#with_project_id ⇒ Arel::Nodes::Equality
236
237
238
239
240
241
242
|
# File 'lib/queries/query.rb', line 236
def with_project_id
if project_id
table[:project_id].eq(project_id)
else
nil
end
end
|