Class: Queries::Extract::Filter

Inherits:
Query::Filter show all
Includes:
Concerns::Citations, Concerns::Confidences, Concerns::Containable, Concerns::DataAttributes, Concerns::DateRanges, Concerns::Protocols, Concerns::Tags, Helpers
Defined in:
lib/queries/extract/filter.rb

Constant Summary collapse

PARAMS =
[
  :collection_object_id,
  :descendants,
  :exact_verbatim_anatomical_origin,
  :extract_end_date_range,
  :extract_id,
  :extract_origin,
  :extract_start_date_range,
  :otu_id,
  :repository_id,
  :sequences,
  :taxon_name_id,
  :verbatim_anatomical_origin,
  collection_object_id: [],
  extract_id: [],
  otu_id: [],
  repository_id: [],
  taxon_name_id: [],
].freeze

Constants inherited from Query::Filter

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

Instance Attribute Summary collapse

Attributes inherited from Query::Filter

#anatomical_part_query, #api, #asserted_distribution_query, #asserted_environment_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 included from Helpers

#boolean_param, #integer_param, #negate_facet, #split_pairs, #split_repeated_pairs, #tri_value_array

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?, #only_project_or_less?, #paging_state, params, #permitted_params, #process_url_into_params, #project_id_facet, 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:

  • query_params (Hash) —

    are permitted params



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/queries/extract/filter.rb', line 83

def initialize(query_params)
  super

  @collection_object_id = params[:collection_object_id]
  @descendants = boolean_param(params, :descendants)
  @exact_verbatim_anatomical_origin = params[:exact_verbatim_anatomical_origin]
  @extract_end_date_range = params[:extract_end_date_range]
  @extract_origin = params[:extract_origin]
  @extract_id = params[:extract_id]
  @extract_start_date_range = params[:extract_start_date_range]
  @otu_id = params[:otu_id]
  @repository_id = params[:repository_id]
  @sequences = boolean_param(params, :sequences)
  @taxon_name_id = params[:taxon_name_id]
  @verbatim_anatomical_origin = params[:verbatim_anatomical_origin]

  set_confidences_params(params)
  set_containable_params(params)
  set_citations_params(params)
  set_data_attributes_params(params)
  set_date_params(params)
  set_tags_params(params)
  set_protocols_params(params)
end

Instance Attribute Details

#collection_object_id ⇒ Array of Repository#id

Returns:



41
42
43
# File 'lib/queries/extract/filter.rb', line 41

def collection_object_id
  @collection_object_id
end

#descendants ⇒ Object

Returns the value of attribute descendants.



47
48
49
# File 'lib/queries/extract/filter.rb', line 47

def descendants
  @descendants
end

#exact_verbatim_anatomical_origin ⇒ Boolean?

Parameters:

  • extract_anatomical_origin (String) —

    'true', 'false', nil

Returns:

  • (Boolean, nil)


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

def exact_verbatim_anatomical_origin
  @exact_verbatim_anatomical_origin
end

#extract_end_date_range ⇒ Date? (private)

Parameters:

  • extract_end_date_range (String) —

    yyyy-mm-dd

Returns:

  • (Date, nil)


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

def extract_end_date_range
  @extract_end_date_range
end

#extract_id ⇒ Array

Parameters:

  • extract_id (Numeric, String, Array) —

    a set of extract#id

Returns:

  • (Array)


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

def extract_id
  @extract_id
end

#extract_origin ⇒ String?

Parameters:

  • see (String) —

    originates_from in app/models/extract.rb for legal values

Returns:

  • (String, nil)


66
67
68
# File 'lib/queries/extract/filter.rb', line 66

def extract_origin
  @extract_origin
end

#extract_start_date_range ⇒ Date? (private)

Parameters:

  • extract_start_date_range (String) —

    yyyy-mm-dd

Returns:

  • (Date, nil)


52
53
54
# File 'lib/queries/extract/filter.rb', line 52

def extract_start_date_range
  @extract_start_date_range
end

#otu_id ⇒ Array of Repository#id

Returns:



38
39
40
# File 'lib/queries/extract/filter.rb', line 38

def otu_id
  @otu_id
end

#repository_id ⇒ Array of Repository#id

Returns:



35
36
37
# File 'lib/queries/extract/filter.rb', line 35

def repository_id
  @repository_id
end

#sequences ⇒ Boolean

Parameters:

  • (String, Boolean, nil)

Returns:

  • (Boolean)


61
62
63
# File 'lib/queries/extract/filter.rb', line 61

def sequences
  @sequences
end

#taxon_name_id ⇒ Protonym.id?

Return all extracts linked to OTUs AND CollectionObject that is self or descendant linked to this TaxonName

Returns:

  • (Protonym.id, nil) —

    return all extracts linked to OTUs AND CollectionObject that is self or descendant linked to this TaxonName



46
47
48
# File 'lib/queries/extract/filter.rb', line 46

def taxon_name_id
  @taxon_name_id
end

#verbatim_anatomical_origin ⇒ String?

Parameters:

  • anatomical_origin (String)

Returns:

  • (String, nil)


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

def verbatim_anatomical_origin
  @verbatim_anatomical_origin
end

Instance Method Details

#anatomical_part_query_facet ⇒ Object



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

def anatomical_part_query_facet
  return nil if anatomical_part_query.nil?

  ::Extract
    .joins(:related_origin_relationships)
    .where(origin_relationships: { old_object_type: 'AnatomicalPart' })
    .where("origin_relationships.old_object_id IN (#{ anatomical_part_query.all.select(:id).to_sql })")
    .distinct
end

#and_clauses ⇒ Array

Returns:

  • (Array)


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

def and_clauses
  [
    extract_id_facet,
    attribute_exact_facet(:verbatim_anatomical_origin),
    date_made_facet,
    repository_id_facet,
  ]
end

#collection_object_id_facet ⇒ Object



197
198
199
200
# File 'lib/queries/extract/filter.rb', line 197

def collection_object_id_facet
  return nil if collection_object_id.empty?
  ::Extract.joins(:origin_collection_objects).where(collection_objects: {id: collection_object_id})
end

#collection_object_query_facet ⇒ Object



242
243
244
245
246
247
248
249
250
251
# File 'lib/queries/extract/filter.rb', line 242

def collection_object_query_facet
  return nil if collection_object_query.nil?
  s = 'WITH query_co_exs AS (' + collection_object_query.all.to_sql + ') ' +
    ::Extract
    .joins(:origin_collection_objects)
    .joins('JOIN query_co_exs as query_co_exs1 on collection_objects.id = query_co_exs1.id')
    .to_sql

  ::Extract.from('(' + s + ') as extracts')
end

#date_made_facet ⇒ Object

TODO: Abstract to single date store range helper



162
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
# File 'lib/queries/extract/filter.rb', line 162

def date_made_facet
  return nil if extract_start_date_range.nil?
  a = extract_start_date_range
  sy,sm,sd = a.year, a.month, a.day
  b = extract_end_date_range
  ey,em,ed = b.year, b.month, b.day

  # 5 possible ranges to consider

  ranges = []

  if sy < ey
    # b/w years
    ranges.push table[:year_made].gt(sy).and(table[:year_made].lt(ey))

    # b/w months start
    ranges.push table[:year_made].eq(sy).and(table[:month_made].gt(sm))

    # b/w months end
    ranges.push table[:year_made].eq(ey).and(table[:month_made].lt(em))
  end

  # days in start month
  ranges.push table[:year_made].eq(sy).and(table[:month_made].eq(sm)).and(table[:day_made].gteq(sd)).and(table[:day_made].lteq(ed))

  # days in end month
  ranges.push table[:year_made].eq(ey).and(table[:month_made].eq(em)).and(table[:day_made].lteq(ed))

  a = ranges.shift
  ranges.each do |r|
    a = a.or(r)
  end
  a
end

#extract_id_facet ⇒ Object



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

def extract_id_facet
  return nil if extract_id.empty?
  table[:id].in(extract_id)
end

#extract_origin_facet ⇒ Object



146
147
148
149
# File 'lib/queries/extract/filter.rb', line 146

def extract_origin_facet
  return nil if extract_origin.nil?
  ::Extract.joins(:related_origin_relationships).where(origin_relationships: {old_object_type: extract_origin})
end

#merge_clauses ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/queries/extract/filter.rb', line 285

def merge_clauses
  [
    anatomical_part_query_facet,
    observation_query_facet,
    collection_object_query_facet,
    otu_query_facet,

    collection_object_id_facet,
    extract_origin_facet,
    otu_id_facet,
    sequences_facet,
    taxon_name_id_facet,
  ]
end

#observation_query_facet ⇒ Object



254
255
256
257
258
259
260
261
262
263
# File 'lib/queries/extract/filter.rb', line 254

def observation_query_facet
  return nil if observation_query.nil?
  s = 'WITH query_obs_extracts AS (' + observation_query.all.to_sql + ') ' +
      ::Extract
        .joins(:observations)
        .joins('JOIN query_obs_extracts as query_obs_extracts1 on observations.id = query_obs_extracts1.id')
        .to_sql

  ::Extract.from('(' + s + ') as extracts').distinct
end

#otu_id_facet ⇒ Object



138
139
140
141
142
143
144
# File 'lib/queries/extract/filter.rb', line 138

def otu_id_facet
  return nil if otu_id.empty?
  a = ::Extract.joins(:origin_otus).where(otus: {id: otu_id})
  b = ::Extract.joins(origin_collection_objects: [:otus]).where(otus: {id: otu_id})

  ::Extract.from("((#{a.to_sql}) UNION (#{b.to_sql})) as extracts")
end

#otu_query_facet ⇒ Object

!! Targets origins of both Otu, and Determined specimens



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/queries/extract/filter.rb', line 222

def otu_query_facet
  return nil if otu_query.nil?
  w = 'WITH query_otu_exs_a AS (' + otu_query.all.to_sql + ') '

  u1 = ::Extract
    .joins(:origin_otus)
    .joins('JOIN query_otu_exs_a as query_otu_exs_a1 on otus.id = query_otu_exs_a1.id')
    .to_sql

  u2 = ::Extract
    .joins(origin_collection_objects: [:taxon_determinations])
    .joins('JOIN query_otu_exs_a as query_otu_exs_a2 on taxon_determinations.otu_id = query_otu_exs_a2.id')
    .where('taxon_determinations.position = 1')
    .to_sql

  s = w + ::Extract.from("((#{u1}) UNION (#{u2})) as extracts").to_sql

  ::Extract.from('(' + s + ') as extracts')
end

#repository_id_facet ⇒ Object



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

def repository_id_facet
  return nil if repository_id.empty?
  table[:repository_id].in(repository_id)
end

#sequences_facet ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'lib/queries/extract/filter.rb', line 151

def sequences_facet
  return nil if sequences.nil?

  subquery = ::OriginRelationship.where(
    ::OriginRelationship.arel_table[:old_object_id].eq(table[:id])
    .and(::OriginRelationship.arel_table[:new_object_type].eq('Sequence')))
    .arel.exists
  ::Extract.where(sequences ? subquery : subquery.not)
end

#taxon_name_id_facet ⇒ Object

TODO: with() TODO: this is not a join, but an IN x2 UNION, i.e. there is likely room for optimization via a join.



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/queries/extract/filter.rb', line 205

def taxon_name_id_facet
  return nil if taxon_name_id.empty?

  o = nil
  if descendants
    o = ::Otu.descendant_of_taxon_name(taxon_name_id)
  else
    o = ::Otu.where(taxon_name_id:)
  end

  a = ::Extract.joins(:origin_otus).where(otus: o)
  b = ::Extract.joins(:origin_collection_objects).where(collection_objects: ::CollectionObject.joins(:otus).where(otus: o))

  ::Extract.from("((#{a.to_sql}) UNION (#{b.to_sql})) as extracts")
end