def _do_search_by_product(self, query, return_fields=False, select_field_names=None, with_source_ids=False, source_filter=None, limit=None): if source_filter: product_queries = list(self._get_product_queries(source_filter)) if not product_queries: # No products match our source filter, so there will be no search results regardless. raise ValueError('No products match source filter: ' % source_filter) if len(product_queries) > 1: raise RuntimeError( "Multi-product source filters are not supported. Try adding 'product' field" ) source_queries, source_product = product_queries[0] dataset_fields = source_product.metadata_type.dataset_fields source_exprs = tuple( fields.to_expressions(dataset_fields.get, **source_queries)) else: source_exprs = None product_queries = list(self._get_product_queries(query)) if not product_queries: product = query.get('product', None) if product is None: raise ValueError('No products match search terms: %r' % query) else: raise ValueError(f"No such product: {product}") for q, product in product_queries: dataset_fields = product.metadata_type.dataset_fields query_exprs = tuple(fields.to_expressions(dataset_fields.get, **q)) select_fields = None if return_fields: # if no fields specified, select all if select_field_names is None: select_fields = tuple( field for name, field in dataset_fields.items() if not field.affects_row_selection) else: select_fields = tuple(dataset_fields[field_name] for field_name in select_field_names) with self._db.connect() as connection: yield (product, connection.search_datasets( query_exprs, source_exprs, select_fields=select_fields, limit=limit, with_source_ids=with_source_ids))
def test_build_query_expressions(): _sat_field = SimpleDocField('platform', None, None, None) _sens_field = SimpleDocField('instrument', None, None, None) _lat_field = NumericRangeDocField('lat', None, None, None) _fields = { 'platform': _sat_field, 'instrument': _sens_field, 'lat': _lat_field } assert [EqualsExpression(_sat_field, "LANDSAT_8") ] == to_expressions(_fields.get, platform="LANDSAT_8") assert [ RangeBetweenExpression(_lat_field, 4, 23.0, _range_class=NumericRange) ] == to_expressions(_fields.get, lat=Range(4, 23))
def make_query_expr(self, query, custom_offsets): """ Generate query expressions including queries based on custom fields """ product_queries = list(self._get_product_queries(query)) custom_query = dict() if not product_queries: # The key, values in query that are un-machable with info # in metadata types and product definitions, perhaps there are custom # fields, will need to handle custom fields separately canonical_query = query.copy() custom_query = { key: canonical_query.pop(key) for key in custom_offsets if key in canonical_query } product_queries = list(self._get_product_queries(canonical_query)) if not product_queries: raise ValueError('No products match search terms: %r' % query) for q, product in product_queries: dataset_fields = product.metadata_type.dataset_fields query_exprs = tuple(fields.to_expressions(dataset_fields.get, **q)) custom_query_exprs = tuple( self.get_custom_query_expressions(custom_query, custom_offsets)) yield product, query_exprs + custom_query_exprs
def _do_time_count(self, period, query, ensure_single=False): if 'time' not in query: raise ValueError( 'Counting through time requires a "time" range query argument') query = dict(query) start, end = query['time'] del query['time'] product_queries = list(self._get_product_queries(query)) if ensure_single: if len(product_queries) == 0: raise ValueError('No products match search terms: %r' % query) if len(product_queries) > 1: raise ValueError( 'Multiple products match single query search: %r' % ([dt.name for q, dt in product_queries], )) for q, product in product_queries: dataset_fields = product.metadata_type.dataset_fields query_exprs = tuple(fields.to_expressions(dataset_fields.get, **q)) with self._db.connect() as connection: yield product, list( connection.count_datasets_through_time( start, end, period, dataset_fields.get('time'), query_exprs))
def _do_count_by_product(self, query): product_queries = self._get_product_queries(query) for q, product in product_queries: dataset_fields = product.metadata_type.dataset_fields query_exprs = tuple(fields.to_expressions(dataset_fields.get, **q)) with self._db.connect() as connection: count = connection.count_datasets(query_exprs) if count > 0: yield product, count
def test_build_query_expressions(): assert [EqualsExpression(_sat_field, "LANDSAT_8")] == to_expressions(_fields.get, platform="LANDSAT_8") assert [ RangeBetweenExpression(_lat_field, 4, 23.0, _range_class=NumericRange) ] == to_expressions(_fields.get, lat=Range(4, 23))