Class: Queries::Person::Filter

Inherits:
Query::Filter show all
Includes:
Concerns::DataAttributes, Concerns::Notes, Concerns::Tags
Defined in:
lib/queries/person/filter.rb

Constant Summary collapse

PARAMS =
[
  :active_after_year,
  :active_before_year,
  :born_after_year,
  :born_before_year,
  :died_after_year,
  :died_before_year,
  :except_project_id,
  :first_name,
  :last_name,
  :last_name_starts_with,
  :levenshtein_cuttoff,
  :name,
  :only_project_id,
  :person_id,
  :prefix,
  :regex, # !! DO NOT EXPOSE TO EXTERNAL API
  :repeated_total,
  :suffix,
  :use_max,
  :use_min,

  exact: [],
  except_project_id: [],
  except_role: [],
  only_project_id: [],
  person_id: [],
  role: [],
  with: [],
  without: [],
].freeze

Constants inherited from Query::Filter

Query::Filter::FILTER_QUERIES, Query::Filter::SUBQUERIES

Instance Attribute Summary collapse

Attributes inherited from Query::Filter

#api, #asserted_distribution_query, #biological_association_query, #biological_associations_graph_query, #collecting_event_query, #collection_object_query, #content_query, #controlled_vocabulary_term_query, #data_attribute_query, #depiction_query, #descriptor_query, #document_query, #dwc_occurrence_query, #extract_query, #field_occurrence_query, #image_query, #loan_query, #object_global_id, #observation_query, #order_by, #otu_query, #page, #paginate, #params, #per, #person_query, #project_id, #recent, #recent_target, #sound_query, #taxon_name_query, #venn, #venn_mode

Attributes inherited from Query

#query_string, #terms

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Query::Filter

#all, #all_and_clauses, #all_merge_clauses, #annotator_and_clauses, #annotator_merge_clauses, annotator_params, api_excluded_params, #apply_venn, #attribute_exact_facet, base_filter, base_query_name, base_query_to_h, #deep_permit, included_annotator_facets, instantiated_base_filter, inverted_subqueries, #model_id_facet, #object_global_id_facet, #only_project?, params, #permitted_params, #process_url_into_params, query_name, #query_name, #set_nested_queries, #shared_and_clauses, #subquery_vector, #target_and_clauses, #venn_query

Methods inherited from Query

#alphabetic_strings, #alphanumeric_strings, base_name, #base_name, #base_query, #build_terms, #cached_facet, #end_wildcard, #levenshtein_distance, #match_ordered_wildcard_pieces_in_cached, #no_terms?, referenced_klass, #referenced_klass, #referenced_klass_except, #referenced_klass_intersection, #referenced_klass_union, #start_and_end_wildcard, #start_wildcard, #table, #wildcard_pieces

Constructor Details

#initialize(query_params = {}) ⇒ Filter

Returns a new instance of Filter.

[View source]

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/queries/person/filter.rb', line 144

def initialize(query_params = {})
  super

  @active_after_year = params[:active_after_year]
  @active_before_year = params[:active_before_year]
  @born_after_year = params[:born_after_year]
  @born_before_year = params[:born_before_year]
  @died_after_year = params[:died_after_year]
  @died_before_year = params[:died_before_year]
  @exact = params[:exact]
  @except_project_id = params[:except_project_id]
  @except_role = params[:except_role]
  @first_name = params[:first_name]
  @last_name = params[:last_name]
  @last_name_starts_with = params[:last_name_starts_with]
  @levenshtein_cuttoff = params[:levenshtein_cuttoff]
  @name = params[:name]
  @only_project_id = params[:only_project_id]
  @regex = params[:regex]
  @repeated_total = params[:repeated_total]
  @role = params[:role]
  @use_max = params[:use_max]
  @use_min = params[:use_min]
  @with = params[:with]
  @without = params[:without]

  set_tags_params(params)
  set_data_attributes_params(params)
  set_notes_params(params)
end

Instance Attribute Details

#active_after_yearString?

Returns:

  • (String, nil)

45
46
47
# File 'lib/queries/person/filter.rb', line 45

def active_after_year
  @active_after_year
end

#active_before_yearString?

Returns:

  • (String, nil)

48
49
50
# File 'lib/queries/person/filter.rb', line 48

def active_before_year
  @active_before_year
end

#born_after_yearString?

Returns:

  • (String, nil)

51
52
53
# File 'lib/queries/person/filter.rb', line 51

def born_after_year
  @born_after_year
end

#born_before_yearString?

Returns:

  • (String, nil)

54
55
56
# File 'lib/queries/person/filter.rb', line 54

def born_before_year
  @born_before_year
end

#died_after_yearString?

Returns:

  • (String, nil)

57
58
59
# File 'lib/queries/person/filter.rb', line 57

def died_after_year
  @died_after_year
end

#died_before_yearString?

Returns:

  • (String, nil)

60
61
62
# File 'lib/queries/person/filter.rb', line 60

def died_before_year
  @died_before_year
end

#exactArray

Returns values are attributes that should be wildcarded:

last_name, first_name,  suffix, prefix, name

When ‘name` then matches cached.

Returns:

  • (Array)

    values are attributes that should be wildcarded:

    last_name, first_name,  suffix, prefix, name
    

    When ‘name` then matches cached


74
75
76
# File 'lib/queries/person/filter.rb', line 74

def exact
  @exact
end

#except_project_idArray

Returns only return people with roles in this project(s) or roles through Sources in ProjectSources.

Returns:

  • (Array)

    only return people with roles in this project(s) or roles through Sources in ProjectSources


64
65
66
# File 'lib/queries/person/filter.rb', line 64

def except_project_id
  @except_project_id
end

#except_roleArray

Returns Exclude all People linked by this Role.

Parameters:

  • role (Array, String)

    A valid role name like ‘Author’ or array like [‘TaxonDeterminer’, ‘SourceEditor’]. See Role descendants.

Returns:

  • (Array)

    Exclude all People linked by this Role


80
81
82
# File 'lib/queries/person/filter.rb', line 80

def except_role
  @except_role
end

#first_nameString?

Returns also matches any AlternateValue.

Returns:

  • (String, nil)

    also matches any AlternateValue


84
85
86
# File 'lib/queries/person/filter.rb', line 84

def first_name
  @first_name
end

#last_nameString?

Returns also matches any AlternateValue.

Returns:

  • (String, nil)

    also matches any AlternateValue


88
89
90
# File 'lib/queries/person/filter.rb', line 88

def last_name
  @last_name
end

#last_name_starts_withObject

Returns the value of attribute last_name_starts_with.


90
91
92
# File 'lib/queries/person/filter.rb', line 90

def last_name_starts_with
  @last_name_starts_with
end

#levenshtein_cuttoffInteger?

Returns matches cached, records less than this edit distance are returned !! requires ‘name` or is ignored.

Returns:

  • (Integer, nil)

    matches cached, records less than this edit distance are returned !! requires ‘name` or is ignored


95
96
97
# File 'lib/queries/person/filter.rb', line 95

def levenshtein_cuttoff
  @levenshtein_cuttoff
end

#nameString?

Returns where against ‘cached`.

Returns:

  • (String, nil)

    where against ‘cached`


99
100
101
# File 'lib/queries/person/filter.rb', line 99

def name
  @name
end

#only_project_idArray

Returns only return people with roles in this project(s) or roles through Sources in ProjectSources.

Returns:

  • (Array)

    only return people with roles in this project(s) or roles through Sources in ProjectSources


68
69
70
# File 'lib/queries/person/filter.rb', line 68

def only_project_id
  @only_project_id
end

#person_idArray

Returns:

  • (Array)

42
43
44
# File 'lib/queries/person/filter.rb', line 42

def person_id
  @person_id
end

#prefixString?

Returns also matches any AlternateValue.

Returns:

  • (String, nil)

    also matches any AlternateValue


103
104
105
# File 'lib/queries/person/filter.rb', line 103

def prefix
  @prefix
end

#regexString?

Returns a regular expression, Postgres compatible, matches against cached.

Returns:

  • (String, nil)

    a regular expression, Postgres compatible, matches against cached


111
112
113
# File 'lib/queries/person/filter.rb', line 111

def regex
  @regex
end

#repeated_totalString?

Returns the number of times this name must be an identical match must be 2 or higher or will be ignored.

Returns:

  • (String, nil)

    the number of times this name must be an identical match must be 2 or higher or will be ignored


116
117
118
# File 'lib/queries/person/filter.rb', line 116

def repeated_total
  @repeated_total
end

#roleArray

Parameters:

  • role (Array, String)

    A valid role name like ‘Author’ or array like [‘TaxonDeterminer’, ‘SourceEditor’]. See Role descendants.

Returns:

  • (Array)

121
122
123
# File 'lib/queries/person/filter.rb', line 121

def role
  @role
end

#suffixString?

Returns also matches any AlternateValue.

Returns:

  • (String, nil)

    also matches any AlternateValue


107
108
109
# File 'lib/queries/person/filter.rb', line 107

def suffix
  @suffix
end

#use_maxString?

Returns the maximum number of roles the Person must be in, further scoped to only counting ‘role` when provided.

Returns:

  • (String, nil)

    the maximum number of roles the Person must be in, further scoped to only counting ‘role` when provided


125
126
127
# File 'lib/queries/person/filter.rb', line 125

def use_max
  @use_max
end

#use_minString?

Returns the minimum number of roles the Person must be in, further scoped to only counting ‘role` when provided.

Returns:

  • (String, nil)

    the minimum number of roles the Person must be in, further scoped to only counting ‘role` when provided


129
130
131
# File 'lib/queries/person/filter.rb', line 129

def use_min
  @use_min
end

#withArray

Parameters:

  • with (Array of strings)

    legal values are first_name, prefix, suffix only return names where the field provided is not nil

Returns:

  • (Array)

135
136
137
# File 'lib/queries/person/filter.rb', line 135

def with
  @with
end

#withoutArray

Parameters:

  • without (Array of strings)

    legal values are first_name, prefix, suffix only return names where the field provided is nil

Returns:

  • (Array)

141
142
143
# File 'lib/queries/person/filter.rb', line 141

def without
  @without
end

Class Method Details

.api_except_paramsObject

[View source]

175
176
177
# File 'lib/queries/person/filter.rb', line 175

def self.api_except_params
  [:regex]
end

Instance Method Details

#active_after_year_facetObject

[View source]

236
237
238
239
240
# File 'lib/queries/person/filter.rb', line 236

def active_after_year_facet
  return nil if active_after_year.nil?
  table[:year_active_start].gt(active_after_year)
    .or(table[:year_active_end].gt(active_after_year))
end

#active_before_year_facetObject

[View source]

242
243
244
245
246
# File 'lib/queries/person/filter.rb', line 242

def active_before_year_facet
  return nil if active_before_year.nil?
  table[:year_active_start].lt(active_before_year)
    .or(table[:year_active_end].lt(active_before_year))
end

#and_clausesObject

[View source]

395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/queries/person/filter.rb', line 395

def and_clauses
  clauses = [
    active_after_year_facet,
    active_before_year_facet,
    born_after_year_facet,
    born_before_year_facet,
    died_after_year_facet,
    died_before_year_facet,
    last_name_starts_with_facet,
    name_facet,
    with_facet,
    without_facet,
  ]
end

#born_after_year_facetObject

[View source]

216
217
218
219
# File 'lib/queries/person/filter.rb', line 216

def born_after_year_facet
  return nil if born_after_year.nil?
  table[:year_born].gt(born_after_year)
end

#born_before_year_facetObject

[View source]

221
222
223
224
# File 'lib/queries/person/filter.rb', line 221

def born_before_year_facet
  return nil if born_before_year.nil?
  table[:year_born].lt(born_before_year)
end

#died_after_year_facetObject

[View source]

226
227
228
229
# File 'lib/queries/person/filter.rb', line 226

def died_after_year_facet
  return nil if died_after_year.nil?
  table[:year_died].gt(died_after_year)
end

#died_before_year_facetObject

[View source]

231
232
233
234
# File 'lib/queries/person/filter.rb', line 231

def died_before_year_facet
  return nil if died_before_year.nil?
  table[:year_died].lt(died_before_year)
end

#except_project_id_facetObject

[View source]

378
379
380
381
382
383
384
385
386
387
388
# File 'lib/queries/person/filter.rb', line 378

def except_project_id_facet
  return nil if except_project_id.empty?

  w1 = role_table[:project_id].not_in(except_project_id)
  w2 = ::ProjectSource.arel_table[:project_id].not_in(except_project_id)

  a = ::Person.joins(:roles).where(w1.to_sql)
  b = ::Person.joins(sources: [:project_sources]).where( w2.to_sql)

  referenced_klass_union([a,b])
end

#except_role_facetObject

[View source]

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/queries/person/filter.rb', line 295

def except_role_facet
  return nil if except_role.empty?
  #  ::Person.left_outer_joins(:roles)
  #    .where( roles: {person_id: nil})
  #    .or( ::Person.left_outer_joins(:roles).where.not( role_table[:type].in(except_role)) )
  #    .distinct

  # ::Person.joins("LEFT JOIN roles on roles.person_id = people.id AND roles.type IN (#{except_role.collect{|r| "'#{r}'"}.join(',')})")
  #   .where( roles: {id: nil})
  #   .distinct

  ::Person.joins(
    table.join(role_table, Arel::Nodes::OuterJoin).on(
      table[:id].eq(role_table[:person_id]).and(role_table[:type]).in(except_role)
    ).join_sources
  ).merge(
    ::Role.where(id: nil)
  ).distinct
end

#last_name_starts_with_facetObject

[View source]

285
286
287
288
# File 'lib/queries/person/filter.rb', line 285

def last_name_starts_with_facet
  return nil if last_name_starts_with.blank? || levenshtein_cuttoff.present?
  table[:last_name].matches(last_name_starts_with + '%')
end

#levenshtein_facetObject

[View source]

362
363
364
365
366
367
# File 'lib/queries/person/filter.rb', line 362

def levenshtein_facet
  return nil unless levenshtein_cuttoff && (name.present?)
  ::Person.where(
    levenshtein_distance(:cached, name).lteq(levenshtein_cuttoff).to_sql
  )
end

#merge_clausesObject

[View source]

410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/queries/person/filter.rb', line 410

def merge_clauses
  [
    except_project_id_facet,
    except_role_facet,
    levenshtein_facet,
    name_part_facet(:first_name),
    name_part_facet(:last_name),
    name_part_facet(:prefix),
    name_part_facet(:suffix),
    only_project_id_facet,
    regex_facet,
    repeated_total_facet,
    role_facet,
    use_facet,
  ]
end

#name_facetObject

[View source]

276
277
278
279
280
281
282
283
# File 'lib/queries/person/filter.rb', line 276

def name_facet
  return nil if name.nil? || levenshtein_cuttoff.present?
  if exact.include?('name')
    table[:cached].eq(name)
  else
    table[:cached].matches('%' + name + '%')
  end
end

#name_part_facet(part = :last_name) ⇒ Object

[View source]

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/queries/person/filter.rb', line 248

def name_part_facet(part = :last_name)
  v = send(part)

  return nil if v.nil?

  q = ::Person.left_outer_joins(:alternate_values)
  a = ::AlternateValue.arel_table

  w1, w2 = nil, nil

  if exact.include?(part.to_s)
    w = '%' + v + '%'
    w1 = table[part].matches(w)
    w2 = a[:value].matches(w)
  else
    w1 = table[part].eq(v)
    w2 = a[:value].eq(v)
  end

  q.where( w1.or(w2).to_sql ).distinct
end

#only_project_id_facetObject

[View source]

369
370
371
372
373
374
375
376
# File 'lib/queries/person/filter.rb', line 369

def only_project_id_facet
  return nil if only_project_id.empty?

  a = ::Person.joins(:roles).where(roles: {project_id: only_project_id})
  b = ::Person.joins(sources: [:project_sources]).where( project_sources: {project_id: only_project_id})

  referenced_klass_union([a,b])
end

#project_id_facetObject

Applies specificly to model, there is no such thing in Person

[View source]

391
392
393
# File 'lib/queries/person/filter.rb', line 391

def project_id_facet
  nil
end

#regex_facetObject

[View source]

271
272
273
274
# File 'lib/queries/person/filter.rb', line 271

def regex_facet
  return nil if regex.blank?
  ::Person.where('cached ~* ?', regex)
end

#repeated_total_facetObject

[View source]

315
316
317
318
319
320
# File 'lib/queries/person/filter.rb', line 315

def repeated_total_facet
  return nil if repeated_total.blank? || repeated_total.to_i < 2
  ::Person.where(
    cached: ::Person.select(:cached).group(:cached).having('COUNT(cached) > ?', repeated_total)
  )
end

#role_facetObject

[View source]

290
291
292
293
# File 'lib/queries/person/filter.rb', line 290

def role_facet
  return nil if role.empty?
  ::Person.joins(:roles).where( role_table[:type].in(role) ).distinct
end

#role_tableArel::Table

Returns:

  • (Arel::Table)
[View source]

204
205
206
# File 'lib/queries/person/filter.rb', line 204

def role_table
  ::Role.arel_table
end

#use_facetObject

[View source]

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/queries/person/filter.rb', line 322

def use_facet
  return nil if (use_min.blank? && use_max.blank?)
  min_max = [use_min&.to_i, use_max&.to_i ].compact

  q = ::Person.joins(:roles)
    .group('people.id, roles.person_id')
    .having("COUNT(roles.person_id) >= #{min_max[0]}")

  if !role.empty?
    q = q.where(role_table[:type].in(role))
  end

  # Untested
  q = q.having("COUNT(roles.person_id) <= #{min_max[1]}") if min_max[1]

  ::Person.from('(' + q.to_sql + ') as people').distinct
end

#with_facetObject

[View source]

340
341
342
343
344
345
346
347
348
349
# File 'lib/queries/person/filter.rb', line 340

def with_facet
  return nil if with.empty?
  a = with.shift
  q = table[a.to_sym].not_eq(nil)

  with.each do |f|
    q = q.and(table[f.to_sym].not_eq(nil))
  end
  q
end

#without_facetObject

[View source]

351
352
353
354
355
356
357
358
359
360
# File 'lib/queries/person/filter.rb', line 351

def without_facet
  return nil if without.empty?
  a = without.shift
  q = table[a.to_sym].eq(nil)

  without.each do |f|
    q = q.and(table[f.to_sym].eq(nil))
  end
  q
end