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, #conveyance_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, #roll_call, #sound_query, #taxon_name_query, #taxon_name_relationship_query, #venn, #venn_ignore_pagination, #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, #disable_paging, included_annotator_facets, instantiated_base_filter, inverted_subqueries, #model_id_facet, #object_global_id_facet, #only_project?, #paging_state, params, #permitted_params, #process_url_into_params, query_name, #set_nested_queries, #set_paging, set_paging, #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.



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
174
# 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]
  @person_id = params[:person_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



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

def self.api_except_params
  [:regex]
end

Instance Method Details

#active_after_year_facetObject



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

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



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

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



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

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



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

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

#born_before_year_facetObject



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

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

#died_after_year_facetObject



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

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

#died_before_year_facetObject



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

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

#except_project_id_facetObject



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

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



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

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



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

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



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

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

#merge_clausesObject



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

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



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

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



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

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



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

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



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

def project_id_facet
  nil
end

#regex_facetObject



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

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

#repeated_total_facetObject



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

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



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

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)


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

def role_table
  ::Role.arel_table
end

#use_facetObject



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

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



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

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



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

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