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, #descriptor_query, #extract_query, #field_occurrence_query, #image_query, #loan_query, #object_global_id, #observation_query, #otu_query, #page, #paginate, #params, #per, #person_query, #project_id, #recent, #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, #deep_permit, included_annotator_facets, inverted_subqueries, #model_id_facet, #object_global_id_facet, params, #permitted_params, #process_url_into_params, query_name, #query_name, #set_nested_queries, #shared_and_clauses, #subquery_vector, #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
# 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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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)


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

def role_table
  ::Role.arel_table
end

#use_facetObject



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# 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)
    .select('people.*, COUNT(roles.person_id)')
    .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