Class: Queries::CollectingEvent::Filter
- Inherits:
-
Object
- Object
- Queries::CollectingEvent::Filter
- Includes:
- Queries::Concerns::DateRanges, Queries::Concerns::Tags
- Defined in:
- lib/queries/collecting_event/filter.rb
Constant Summary collapse
- ATTRIBUTES =
TODO: likely move to model Params exists for all CollectingEvent attributes except these
(::CollectingEvent.column_names - %w{project_id created_by_id updated_by_id created_at updated_at})
Instance Attribute Summary collapse
-
#collecting_event_wildcards ⇒ Array
Values are ATTRIBUTES that should be wildcarded.
- #collector_ids ⇒ Array
-
#collector_ids_or ⇒ Object
Returns the value of attribute collector_ids_or.
-
#geo_json ⇒ Hash?
In geo_json format (no Feature …) ?!.
-
#geographic_area_ids ⇒ Array
Match only CollectionObjects mapped to CollectingEvents that have these specific ids.
-
#in_labels ⇒ Object
Wildcard wrapped matching any label.
-
#in_verbatim_locality ⇒ Object
TODO: remove for exact/array Wildcard wrapped matching verbatim_locality via ATTRIBUTES.
-
#md5_verbatim_label ⇒ Object
If true then in_labels checks only the MD5.
- #otu_ids ⇒ Array
-
#radius ⇒ Object
Integer in Meters.
-
#recent ⇒ True?
TODO: reffactor to Concern or remove (likely doesn't belong here).
-
#spatial_geographic_areas ⇒ True?
Reference geographic areas to do a spatial query.
-
#wkt ⇒ Object
A spatial representation in well known text.
Instance Method Summary collapse
- #all ⇒ ActiveRecord::Relation
- #and_clauses ⇒ ActiveRecord::Relation
- #attribute_clauses ⇒ Object
- #base_and_clauses ⇒ Array
- #base_merge_clauses ⇒ Object
- #base_query ⇒ Object
-
#collector_ids_facet ⇒ Object
TODO: dry with Source, TaxonName, etc.
-
#geo_json_facet ⇒ Object
Shape is a Hash in GeoJSON format.
-
#initialize(params) ⇒ Filter
constructor
A new instance of Filter.
- #matching_any_label ⇒ Object
- #matching_geographic_area_ids ⇒ Object
- #matching_otu_ids ⇒ Object
-
#matching_spatial_via_geographic_area_ids ⇒ Object
TODO: throttle by size?.
- #matching_verbatim_label_md5 ⇒ Object
- #matching_verbatim_locality ⇒ Object
- #merge_clauses ⇒ Object
- #set_attributes(params) ⇒ Object
- #spatial_query(geometry_type, wkt) ⇒ Object
- #table ⇒ Arel::Table
-
#wkt_facet ⇒ Object
TODO: what is it @param value [String] ?! In def shape=(value) @shape = ::RGeo::GeoJSON.decode(value, json_parser: :json) @shape end.
Constructor Details
#initialize(params) ⇒ Filter
Returns a new instance of Filter.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/queries/collecting_event/filter.rb', line 65 def initialize(params) @in_labels = params[:in_labels] @in_verbatim_locality = params[:in_verbatim_locality] @recent = params[:recent].blank? ? nil : params[:recent].to_i @wkt = params[:wkt] @geo_json = params[:geo_json] @radius = params[:radius].blank? ? 100 : params[:radius] @keyword_ids = params[:keyword_ids].blank? ? [] : params[:keyword_ids] # @spatial_geographic_area_ids = params[:spatial_geographic_areas].blank? ? [] : params[:spatial_geographic_area_ids] @spatial_geographic_areas = (params[:spatial_geographic_areas]&.downcase == 'true' ? true : false) if !params[:spatial_geographic_areas].nil? @md5_verbatim_label = (params[:md5_verbatim_label]&.downcase == 'true' ? true : false) if !params[:md5_verbatim_label].nil? @geographic_area_ids = params[:geographic_area_ids].blank? ? [] : params[:geographic_area_ids] @otu_ids = params[:otu_ids].blank? ? [] : params[:otu_ids] @collector_ids = params[:collector_ids].blank? ? [] : params[:collector_ids] @collector_ids_or = (params[:collector_ids_or]&.downcase == 'true' ? true : false) if !params[:collector_ids_or].nil? @collecting_event_wildcards = params[:collecting_event_wildcards] || [] set_attributes(params) set_dates(params) end |
Instance Attribute Details
#collecting_event_wildcards ⇒ Array
Returns values are ATTRIBUTES that should be wildcarded.
55 56 57 |
# File 'lib/queries/collecting_event/filter.rb', line 55 def collecting_event_wildcards @collecting_event_wildcards end |
#collector_ids ⇒ Array
61 62 63 |
# File 'lib/queries/collecting_event/filter.rb', line 61 def collector_ids @collector_ids end |
#collector_ids_or ⇒ Object
Returns the value of attribute collector_ids_or.
63 64 65 |
# File 'lib/queries/collecting_event/filter.rb', line 63 def collector_ids_or @collector_ids_or end |
#geo_json ⇒ Hash?
Returns in geo_json format (no Feature …) ?!.
41 42 43 |
# File 'lib/queries/collecting_event/filter.rb', line 41 def geo_json @geo_json end |
#geographic_area_ids ⇒ Array
Returns match only CollectionObjects mapped to CollectingEvents that have these specific ids. No spatial calculations are included in this parameter by default. See 'spatial_geographic_areas = true'.
51 52 53 |
# File 'lib/queries/collecting_event/filter.rb', line 51 def geographic_area_ids @geographic_area_ids end |
#in_labels ⇒ Object
Wildcard wrapped matching any label
20 21 22 |
# File 'lib/queries/collecting_event/filter.rb', line 20 def in_labels @in_labels end |
#in_verbatim_locality ⇒ Object
TODO: remove for exact/array Wildcard wrapped matching verbatim_locality via ATTRIBUTES
27 28 29 |
# File 'lib/queries/collecting_event/filter.rb', line 27 def in_verbatim_locality @in_verbatim_locality end |
#md5_verbatim_label ⇒ Object
If true then in_labels checks only the MD5
23 24 25 |
# File 'lib/queries/collecting_event/filter.rb', line 23 def md5_verbatim_label @md5_verbatim_label end |
#otu_ids ⇒ Array
58 59 60 |
# File 'lib/queries/collecting_event/filter.rb', line 58 def otu_ids @otu_ids end |
#radius ⇒ Object
Integer in Meters
37 38 39 |
# File 'lib/queries/collecting_event/filter.rb', line 37 def radius @radius end |
#recent ⇒ True?
TODO: reffactor to Concern or remove (likely doesn't belong here)
31 32 33 |
# File 'lib/queries/collecting_event/filter.rb', line 31 def recent @recent end |
#spatial_geographic_areas ⇒ True?
Reference geographic areas to do a spatial query
45 46 47 |
# File 'lib/queries/collecting_event/filter.rb', line 45 def spatial_geographic_areas @spatial_geographic_areas end |
#wkt ⇒ Object
A spatial representation in well known text
34 35 36 |
# File 'lib/queries/collecting_event/filter.rb', line 34 def wkt @wkt end |
Instance Method Details
#all ⇒ ActiveRecord::Relation
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/queries/collecting_event/filter.rb', line 281 def all a = and_clauses b = merge_clauses q = nil if a && b q = b.where(a).distinct elsif a q = ::CollectingEvent.where(a).distinct elsif b q = b.distinct else q = ::CollectingEvent.includes(:identifiers, :roles, :pinboard_items, :geographic_area, georeferences: [:geographic_item, :error_geographic_item]).all end q = q.order(updated_at: :desc).limit(recent) if recent q end |
#and_clauses ⇒ ActiveRecord::Relation
258 259 260 261 262 263 264 265 266 267 |
# File 'lib/queries/collecting_event/filter.rb', line 258 def and_clauses clauses = base_and_clauses return nil if clauses.empty? a = clauses.shift clauses.each do |b| a = a.and(b) end a end |
#attribute_clauses ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/queries/collecting_event/filter.rb', line 111 def attribute_clauses c = [] ATTRIBUTES.each do |a| if v = send(a) if !v.blank? if collecting_event_wildcards.include?(a) c.push table[a.to_sym].matches('%' + v.to_s + '%') else c.push table[a.to_sym].eq(v) end end end end c end |
#base_and_clauses ⇒ Array
230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/queries/collecting_event/filter.rb', line 230 def base_and_clauses clauses = [] clauses += attribute_clauses clauses += [ between_date_range, matching_geographic_area_ids, matching_verbatim_label_md5, matching_any_label, matching_verbatim_locality, ].compact! clauses end |
#base_merge_clauses ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/queries/collecting_event/filter.rb', line 245 def base_merge_clauses clauses = [ matching_keyword_ids, matching_otu_ids, wkt_facet, geo_json_facet, collector_ids_facet, matching_spatial_via_geographic_area_ids ].compact! clauses end |
#base_query ⇒ Object
107 108 109 |
# File 'lib/queries/collecting_event/filter.rb', line 107 def base_query ::CollectingEvent.select('collecting_events.*') end |
#collector_ids_facet ⇒ Object
TODO: dry with Source, TaxonName, etc.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/queries/collecting_event/filter.rb', line 128 def collector_ids_facet return nil if collector_ids.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('CollectingEvent')) .and(c[:type].eq('Collector')) ) e = c[:id].not_eq(nil) f = c[:person_id].eq_any(collector_ids) b = b.where(e.and(f)) b = b.group(a['id']) b = b.having(a['id'].count.eq(collector_ids.length)) unless collector_ids_or b = b.as('z1_') ::CollectingEvent.joins(Arel::Nodes::InnerJoin.new(b, Arel::Nodes::On.new(b['id'].eq(o['id'])))) end |
#geo_json_facet ⇒ Object
Shape is a Hash in GeoJSON format
172 173 174 175 176 |
# File 'lib/queries/collecting_event/filter.rb', line 172 def geo_json_facet return nil if geo_json.nil? a = RGeo::GeoJSON.decode(geo_json) spatial_query(a.geometry_type.to_s, a.to_s) end |
#matching_any_label ⇒ Object
200 201 202 203 204 |
# File 'lib/queries/collecting_event/filter.rb', line 200 def matching_any_label return nil if in_labels.blank? t = "%#{in_labels}%" table[:verbatim_label].matches(t).or(table[:print_label].matches(t)).or(table[:document_label].matches(t)) end |
#matching_geographic_area_ids ⇒ Object
213 214 215 216 |
# File 'lib/queries/collecting_event/filter.rb', line 213 def matching_geographic_area_ids return nil if geographic_area_ids.empty? || spatial_geographic_areas table[:geographic_area_id].eq_any(geographic_area_ids) end |
#matching_otu_ids ⇒ Object
218 219 220 221 |
# File 'lib/queries/collecting_event/filter.rb', line 218 def matching_otu_ids return nil if otu_ids.empty? ::CollectingEvent.joins(:otus).where(otus: {id: otu_ids}) # table[:geographic_area_id].eq_any(geographic_area_ids) end |
#matching_spatial_via_geographic_area_ids ⇒ Object
TODO: throttle by size?
194 195 196 197 198 |
# File 'lib/queries/collecting_event/filter.rb', line 194 def matching_spatial_via_geographic_area_ids return nil unless spatial_geographic_areas && !geographic_area_ids.empty? a = ::GeographicItem.default_by_geographic_area_ids(geographic_area_ids).ids ::CollectingEvent.joins(:geographic_items).where( ::GeographicItem.contained_by_where_sql( a ) ) end |
#matching_verbatim_label_md5 ⇒ Object
206 207 208 209 210 211 |
# File 'lib/queries/collecting_event/filter.rb', line 206 def matching_verbatim_label_md5 return nil unless md5_verbatim_label && !in_labels.blank? md5 = ::Utilities::Strings.generate_md5(in_labels) table[:md5_of_verbatim_label].eq(md5) end |
#matching_verbatim_locality ⇒ Object
223 224 225 226 227 |
# File 'lib/queries/collecting_event/filter.rb', line 223 def matching_verbatim_locality return nil if in_verbatim_locality.blank? t = "%#{in_verbatim_locality}%" table[:verbatim_locality].matches(t) end |
#merge_clauses ⇒ Object
269 270 271 272 273 274 275 276 277 278 |
# File 'lib/queries/collecting_event/filter.rb', line 269 def merge_clauses clauses = base_merge_clauses return nil if clauses.empty? a = clauses.shift clauses.each do |b| a = a.merge(b) end a end |
#set_attributes(params) ⇒ Object
96 97 98 99 100 |
# File 'lib/queries/collecting_event/filter.rb', line 96 def set_attributes(params) ATTRIBUTES.each do |a| send("#{a}=", params[a.to_sym]) end end |
#spatial_query(geometry_type, wkt) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/queries/collecting_event/filter.rb', line 178 def spatial_query(geometry_type, wkt) case geometry_type when 'Point' ::CollectingEvent .joins(:geographic_items) .where(::GeographicItem.within_radius_of_wkt_sql(wkt, radius )) when 'Polygon', 'MultiPolygon' ::CollectingEvent .joins(:geographic_items) .where(::GeographicItem.contained_by_wkt_sql(wkt)) else nil end end |
#table ⇒ Arel::Table
103 104 105 |
# File 'lib/queries/collecting_event/filter.rb', line 103 def table ::CollectingEvent.arel_table end |
#wkt_facet ⇒ Object
TODO: what is it @param value [String] ?! In def shape=(value)
@shape = ::RGeo::GeoJSON.decode(value, json_parser: :json)
@shape
end
164 165 166 167 168 169 |
# File 'lib/queries/collecting_event/filter.rb', line 164 def wkt_facet return nil if wkt.blank? a = RGeo::WKRep::WKTParser.new b = a.parse(wkt) spatial_query(b.geometry_type.to_s, wkt) end |