Class: Queries::Source::Filter

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

Constant Summary collapse

ATTRIBUTES =
(::Source.core_attributes - %w{bibtex_type title author serial_id} + %w{cached cached_author_string cached_nomenclature_date}).map(&:to_sym).freeze
PARAMS =
[
  *ATTRIBUTES,
  :source_id,
  :taxon_name_id,
  :descendants,
  :author,
  :author_id_or,
  :bibtex_type,
  :citations,
  :citations_on_otus,
  :documents,
  :exact_author,
  :exact_title,
  :in_project,
  :nomenclature,
  :query_term,
  :roles,
  :serial,
  :source_type,
  :title,
  :with_doi,
  :with_pages,
  :with_title,
  :year_end,
  :year_start,
  author_id: [],
  bibtex_type: [],
  citation_object_type: [],
  empty: [],
  not_empty: [],
  serial_id: [],
  source_id: [],
  taxon_name_id: [],
  topic_id: [],
].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

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_except_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.

Parameters:

  • params (Hash)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/queries/source/filter.rb', line 163

def initialize(query_params)
  super

  @author = params[:author]
  @author_id = params[:author_id]
  @author_id_or =  boolean_param(params,:author_id_or)
  @bibtex_type = params[:bibtex_type]
  @citation_object_type = params[:citation_object_type]
  @citations = boolean_param(params,:citations) # TODO: rename coming to reflect conflict with Citations concern
  @citations_on_otus = boolean_param(params,:citations_on_otus)
  @descendants = boolean_param(params, :descendants)
  @documents = boolean_param(params,:documents)
  @exact_author = boolean_param(params,:exact_author)
  @exact_title = boolean_param(params,:exact_title)
  @in_project = boolean_param(params,:in_project)
  @nomenclature = boolean_param(params,:nomenclature)
  @query_string = params[:query_term]&.delete("\u0000") # TODO: likely remove with current permit() paradigm
  @roles = boolean_param(params,:roles)
  @serial = boolean_param(params,:serial)
  @serial_id = params[:serial_id]
  @source_id = params[:source_id]
  @source_type = params[:source_type]
  @taxon_name_id = params[:taxon_name_id]
  @title = params[:title]
  @topic_id = params[:topic_id]
  @with_doi = boolean_param(params, :with_doi)
  @with_pages = boolean_param(params, :with_pages)
  @with_title = boolean_param(params, :with_title)
  @year_end = params[:year_end]
  @year_start = params[:year_start]

  build_terms

  set_data_attributes_params(params)
  set_attributes_params(params)
  set_empty_params(params)
  set_tags_params(params)
  set_notes_params(params)
  set_user_dates(params)
end

Instance Attribute Details

#authorObject

Returns the value of attribute author.



59
60
61
# File 'lib/queries/source/filter.rb', line 59

def author
  @author
end

#author_idObject

Returns the value of attribute author_id.



70
71
72
# File 'lib/queries/source/filter.rb', line 70

def author_id
  @author_id
end

#author_id_orObject

Returns the value of attribute author_id_or.



75
76
77
# File 'lib/queries/source/filter.rb', line 75

def author_id_or
  @author_id_or
end

#bibtex_typeArray, ...

one of the allowed BibTeX types

Returns:

  • (Array, String, nil)


160
161
162
# File 'lib/queries/source/filter.rb', line 160

def bibtex_type
  @bibtex_type
end

#citation_object_typeArray?

TODO: move tc citations concern

Returns:

  • (Array, nil)


117
118
119
# File 'lib/queries/source/filter.rb', line 117

def citation_object_type
  @citation_object_type
end

#citationsBoolean?

!! TODO - conflicts with citations? !! - yes, this is *used in citations*

Returns:

  • (Boolean, nil)


96
97
98
# File 'lib/queries/source/filter.rb', line 96

def citations
  @citations
end

#citations_on_otusBoolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/queries/source/filter.rb', line 138

def citations_on_otus
  @citations_on_otus
end

#descendantsObject

Returns the value of attribute descendants.



133
134
135
# File 'lib/queries/source/filter.rb', line 133

def descendants
  @descendants
end

#documentsBoolean?

Returns:

  • (Boolean, nil)


104
105
106
# File 'lib/queries/source/filter.rb', line 104

def documents
  @documents
end

#exact_authorBoolean?

Returns:

  • (Boolean, nil)


67
68
69
# File 'lib/queries/source/filter.rb', line 67

def exact_author
  @exact_author
end

#exact_titleBoolean?

Returns:

  • (Boolean, nil)


91
92
93
# File 'lib/queries/source/filter.rb', line 91

def exact_title
  @exact_title
end

#in_projectBoolean?

! requires ‘project_id`

Returns:

  • (Boolean, nil)


56
57
58
# File 'lib/queries/source/filter.rb', line 56

def in_project
  @in_project
end

#nomenclatureBoolean?

Returns:

  • (Boolean, nil)


108
109
110
# File 'lib/queries/source/filter.rb', line 108

def nomenclature
  @nomenclature
end

#rolesBoolean?

Returns:

  • (Boolean, nil)


100
101
102
# File 'lib/queries/source/filter.rb', line 100

def roles
  @roles
end

#serialBoolean?

true - with serial_id false - without_serial_id nil - both

Returns:

  • (Boolean, nil)


144
145
146
# File 'lib/queries/source/filter.rb', line 144

def serial
  @serial
end

#serial_idObject

Returns the value of attribute serial_id.



127
128
129
# File 'lib/queries/source/filter.rb', line 127

def serial_id
  @serial_id
end

#source_idObject

TODO: Change to source_id



63
64
65
# File 'lib/queries/source/filter.rb', line 63

def source_id
  @source_id
end

#source_typeString?

Returns:

  • (String, nil)


124
125
126
# File 'lib/queries/source/filter.rb', line 124

def source_type
  @source_type
end

#taxon_name_idProtonym.id?

Return all sources in Citations linked to this name (or descendants option) to this TaxonName

Returns:

  • (Protonym.id, nil)

    return all sources in Citations linked to this name (or descendants option) to this TaxonName



132
133
134
# File 'lib/queries/source/filter.rb', line 132

def taxon_name_id
  @taxon_name_id
end

#titleObject

Returns the value of attribute title.



87
88
89
# File 'lib/queries/source/filter.rb', line 87

def title
  @title
end

#topic_idObject

Returns the value of attribute topic_id.



78
79
80
# File 'lib/queries/source/filter.rb', line 78

def topic_id
  @topic_id
end

#with_doiBoolean?

Returns:

  • (Boolean, nil)


112
113
114
# File 'lib/queries/source/filter.rb', line 112

def with_doi
  @with_doi
end

#with_pagesBoolean?

true - with pages false - without pages nil - both

Returns:

  • (Boolean, nil)


150
151
152
# File 'lib/queries/source/filter.rb', line 150

def with_pages
  @with_pages
end

#with_titleBoolean?

true - with a title false - without a title nil - both

Returns:

  • (Boolean, nil)


156
157
158
# File 'lib/queries/source/filter.rb', line 156

def with_title
  @with_title
end

#year_endObject

Returns the value of attribute year_end.



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

def year_end
  @year_end
end

#year_startObject

Returns the value of attribute year_start.



81
82
83
# File 'lib/queries/source/filter.rb', line 81

def year_start
  @year_start
end

Instance Method Details

#ancestor_otus_joinObject (private)



488
489
490
491
492
493
494
495
496
497
498
# File 'lib/queries/source/filter.rb', line 488

def ancestor_otus_join
  h = Arel::Table.new(:taxon_name_hierarchies)
  c = ::Citation.arel_table
  o = ::Otu.arel_table

  c.join(o, Arel::Nodes::InnerJoin).on(
    o[:id].eq(c[:citation_object_id]).and(c[:citation_object_type].eq('Otu'))
  ).join(h, Arel::Nodes::InnerJoin).on(
    o[:taxon_name_id].eq(h[:descendant_id]).and(h[:ancestor_id].in(taxon_name_id))
  )
end

#ancestor_taxon_name_classifications_joinObject (private)



512
513
514
515
516
517
518
519
520
521
522
523
524
# File 'lib/queries/source/filter.rb', line 512

def ancestor_taxon_name_classifications_join
  return nil if taxon_name_id.nil?

  h = Arel::Table.new(:taxon_name_hierarchies)
  c = ::Citation.arel_table
  t = ::TaxonNameClassification.arel_table

  c.join(t, Arel::Nodes::InnerJoin).on(
    t[:id].eq(c[:citation_object_id]).and(c[:citation_object_type].eq('TaxonNameClassification'))
  ).join(h, Arel::Nodes::InnerJoin).on(
    t[:taxon_name_id].eq(h[:descendant_id]).and(h[:ancestor_id].in(taxon_name_id))
  )
end

#ancestor_taxon_name_relationship_join(join_on = :subject_taxon_name_id) ⇒ Object (private)



526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'lib/queries/source/filter.rb', line 526

def ancestor_taxon_name_relationship_join(join_on = :subject_taxon_name_id)
  return nil if taxon_name_id.nil?

  h = Arel::Table.new(:taxon_name_hierarchies)
  c = ::Citation.arel_table
  t = ::TaxonNameRelationship.arel_table

  c.join(t, Arel::Nodes::InnerJoin).on(
    t[:id].eq(c[:citation_object_id]).and(c[:citation_object_type].eq('TaxonNameRelationship'))
  ).join(h, Arel::Nodes::InnerJoin).on(
    t[join_on].eq(h[:descendant_id]).and(h[:ancestor_id].in(taxon_name_id))
  )
end

#ancestor_taxon_names_joinObject (private)



500
501
502
503
504
505
506
507
508
509
510
# File 'lib/queries/source/filter.rb', line 500

def ancestor_taxon_names_join
  h = Arel::Table.new(:taxon_name_hierarchies)
  c = ::Citation.arel_table
  t = ::TaxonName.arel_table

  c.join(t, Arel::Nodes::InnerJoin).on(
    t[:id].eq(c[:citation_object_id]).and(c[:citation_object_type].eq('TaxonName'))
  ).join(h, Arel::Nodes::InnerJoin).on(
    t[:id].eq(h[:descendant_id]).and(h[:ancestor_id].in(taxon_name_id))
  )
end

#and_clausesObject



471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/queries/source/filter.rb', line 471

def and_clauses
  [
    attribute_exact_facet(:author),
    attribute_exact_facet(:title),
    bibtex_type_facet,
    cached_facet,
    serial_facet,
    serial_id_facet,
    source_type_facet,
    with_pages_facet,
    with_title_facet,
    year_facet,
  ]
end

#author_id_facetObject



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/queries/source/filter.rb', line 280

def author_id_facet
  return nil if author_id.empty?
  o = table
  r = ::Role.arel_table

  a = o.alias('a_')
  b = o.project(a[Arel.star]).from(a)

  c = r.alias('r1')

  b = b.join(c, Arel::Nodes::OuterJoin)
    .on(
      a[:id].eq(c[:role_object_id])
    .and(c[:role_object_type].eq('Source'))
    .and(c[:type].eq('SourceAuthor'))
    )

  e = c[:id].not_eq(nil)
  f = c[:person_id].in(author_id)

  b = b.where(e.and(f))
  b = b.group(a['id'])
  b = b.having(a['id'].count.eq(author_id.length)) unless author_id_or
  b = b.as('aut_z1_')

  ::Source.joins(Arel::Nodes::InnerJoin.new(b, Arel::Nodes::On.new(b['id'].eq(o['id'])))).distinct
end

#bibtex_type_facetObject



233
234
235
236
# File 'lib/queries/source/filter.rb', line 233

def bibtex_type_facet
  return nil if bibtex_type.empty?
  table[:type].eq('Source::Bibtex').and(table[:bibtex_type].in(bibtex_type))
end

#citation_object_type_facetObject



400
401
402
403
404
# File 'lib/queries/source/filter.rb', line 400

def citation_object_type_facet
  return nil if citation_object_type.empty?
  ::Source.joins(:citations)
    .where(citations: {citation_object_type:}).distinct
end

#citations_facetObject



420
421
422
423
424
425
426
427
# File 'lib/queries/source/filter.rb', line 420

def citations_facet
  return nil if citations.nil?
  if citations
    ::Source.joins(:citations).distinct
  else
    ::Source.where.missing(:citations)
  end
end

#document_facetObject

TODO: move to a concern



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

def document_facet
  return nil if documents.nil?

  if documents
    ::Source.joins(:documents, :project_sources).where(project_sources: {project_id:}).distinct
  else
    a = ::Source.where.missing(:documents).distinct
    b = ::Source.joins(:project_sources).where(project_sources: {project_id: }).where.missing(:documentation).distinct

    ::Source.from("((#{a.to_sql}) UNION (#{b.to_sql})) as sources")
  end
end

#identifier_type_facetObject

Over-rides Query::Filter identifier_type_facet to handle with_doi exception



327
328
329
330
331
332
# File 'lib/queries/source/filter.rb', line 327

def identifier_type_facet
  return nil if identifier_type.empty? || with_doi
  q = referenced_klass.joins(:identifiers)
  w = identifier_table[:type].in(identifier_type)
  q.where(w).distinct
end

#in_project_facetObject



313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/queries/source/filter.rb', line 313

def in_project_facet
  return nil if project_id.empty? || in_project.nil?

  if in_project
    ::Source.joins(:project_sources)
      .where(project_sources: {project_id:})
  else
    ::Source.left_outer_joins(:project_sources)
      .where('project_sources.project_id != ? OR project_sources.id IS NULL', project_id) # TODO: probably project_id
      .distinct
  end
end

#merge_clausesObject



452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/queries/source/filter.rb', line 452

def merge_clauses
  s = ::Queries::Query::Filter::SUBQUERIES.select{|k,v| v.include?(:source)}.keys.map(&:to_s)
  [
    *s.collect{|m| query_facets_facet(m)}, # Reference all the Source referencing SUBQUERIES
    author_id_facet,
    citation_object_type_facet,
    citations_facet,
    document_facet,
    empty_fields_facet, # See Queries::Concerns::Empty
    in_project_facet,
    nomenclature_facet,
    not_empty_fields_facet,
    role_facet,
    taxon_name_id_facet,
    topic_id_facet,
    with_doi_facet,
  ]
end

#nomenclature_facetObject



406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/queries/source/filter.rb', line 406

def nomenclature_facet
  return nil if nomenclature.nil?

  if nomenclature
    ::Source.joins(:citations)
      .where(citations: {citation_object_type: ['TaxonName', 'TaxonNameRelationship', 'TaxonNameClassification', 'TypeMaterial']})
      .distinct
  else
    ::Source.left_outer_joins(:citations)
      .where("(citations.citation_object_type NOT IN ('TaxonName','TaxonNameRelationship','TaxonNameClassification','TypeMaterial')) OR (citations.id is null)")
      .distinct
  end
end

#project_id_facetObject

Over-ride the inclusion of this facet at the Filter level.



430
431
432
# File 'lib/queries/source/filter.rb', line 430

def project_id_facet
  nil
end

#project_sources_tableArel::Table

Returns:

  • (Arel::Table)


225
226
227
# File 'lib/queries/source/filter.rb', line 225

def project_sources_table
  ::ProjectSource.arel_table
end

#query_facets_facet(name = nil) ⇒ Object



434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/queries/source/filter.rb', line 434

def query_facets_facet(name = nil)
  return nil if name.nil?

  q = send((name + '_query').to_sym)

  return nil if q.nil?

  n = "query_#{name}_src"

  s = "WITH #{n} AS (" + q.all.to_sql + ') ' +
    ::Source
    .joins(:citations)
    .joins("JOIN #{n} as #{n}1 on citations.citation_object_id = #{n}1.id AND citations.citation_object_type = '#{name.treetop_camelize}'")
    .to_sql

  ::Source.from('(' + s + ') as sources').distinct
end

#role_facetObject

TODO: move to a concern



365
366
367
368
369
370
371
372
373
374
# File 'lib/queries/source/filter.rb', line 365

def role_facet
  return nil if roles.nil?

  if roles
    ::Source.joins(:roles).distinct
  else
    ::Source.left_outer_joins(:roles)
      .where(roles: {id: nil}).distinct
  end
end

#serial_facetObject



390
391
392
393
394
395
396
397
398
# File 'lib/queries/source/filter.rb', line 390

def serial_facet
  return nil if serial.nil?

  if serial
    table[:serial_id].not_eq(nil)
  else
    table[:serial_id].eq(nil)
  end
end

#serial_id_facetObject



276
277
278
# File 'lib/queries/source/filter.rb', line 276

def serial_id_facet
  serial_id.empty? ? nil : table[:serial_id].in(serial_id)
end

#source_type_facetObject



261
262
263
264
# File 'lib/queries/source/filter.rb', line 261

def source_type_facet
  return nil if source_type.blank?
  table[:type].eq(source_type)
end

#taxon_name_id_facetObject

Return all citations on Taxon names and descendants, and optionally OTUs.



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/queries/source/filter.rb', line 244

def taxon_name_id_facet
  return nil if taxon_name_id.empty?

  joins = [
    ancestor_taxon_names_join,
    ancestor_taxon_name_classifications_join,
    ancestor_taxon_name_relationship_join(:subject_taxon_name_id),
    ancestor_taxon_name_relationship_join(:object_taxon_name_id)
  ]

  joins.push ancestor_otus_join if citations_on_otus

  union = joins.collect{|j| '(' + ::Source.joins(:citations).joins( j.join_sources).to_sql + ')'}.join(' UNION ')

  ::Source.from("( #{union} ) as sources").distinct
end

#topic_id_facetObject



308
309
310
311
# File 'lib/queries/source/filter.rb', line 308

def topic_id_facet
  return nil if topic_id.empty?
  ::Source.joins(:citation_topics).where(citation_topics: { topic_id:}).distinct
end

#with_doi_facetObject

TODO: move to generalized code in Identifiers concern



335
336
337
338
339
340
341
342
# File 'lib/queries/source/filter.rb', line 335

def with_doi_facet
  return nil if with_doi.nil?
  if with_doi
    ::Source.joins(:identifiers).where(identifiers: {type: 'Identifier::Global::Doi'}).distinct
  else
    ::Source.left_outer_joins(:identifiers).where("(identifiers.type != 'Identifier::Global::Doi') OR (identifiers.identifier_object_id is null)").distinct
  end
end

#with_pages_facetObject



354
355
356
357
358
359
360
361
362
# File 'lib/queries/source/filter.rb', line 354

def with_pages_facet
  return nil if with_pages.nil?

  if with_pages
    table[:pages].not_eq(nil)
  else
    table[:pages].eq(nil)
  end
end

#with_title_facetObject



344
345
346
347
348
349
350
351
352
# File 'lib/queries/source/filter.rb', line 344

def with_title_facet
  return nil if with_title.nil?

  if with_title
    table[:title].not_eq(nil)
  else
    table[:title].eq(nil)
  end
end

#year_facetObject



266
267
268
269
270
271
272
273
274
# File 'lib/queries/source/filter.rb', line 266

def year_facet
  return nil if year_start.blank?
  if year_start && year_end.present?
    table[:year].gteq(year_start)
      .and(table[:year].lteq(year_end))
  else # only start
    table[:year].eq(year_start)
  end
end