def search_robust(self, **query): """ Return dataset types that match match-able fields and dict of remaining un-matchable fields. :param dict query: :rtype: __generator[(DatasetType, dict)] """ def _listify(v): if isinstance(v, tuple): return list(v) elif isinstance(v, list): return v else: return [v] for type_ in self.get_all(): remaining_matchable = query.copy() # If they specified specific product/metadata-types, we can quickly skip non-matches. if type_.name not in _listify( remaining_matchable.pop('product', type_.name)): continue if type_.metadata_type.name not in _listify( remaining_matchable.pop('metadata_type', type_.metadata_type.name)): continue # Check that all the keys they specified match this product. for key, value in list(remaining_matchable.items()): field = type_.metadata_type.dataset_fields.get(key) if not field: # This type doesn't have that field, so it cannot match. break if not hasattr(field, 'extract'): # non-document/native field continue if field.extract(type_.metadata_doc) is None: # It has this field but it's not defined in the type doc, so it's unmatchable. continue expr = fields.as_expression(field, value) if expr.evaluate(type_.metadata_doc): remaining_matchable.pop(key) else: # A property doesn't match this type, skip to next type. break else: yield type_, remaining_matchable
def get_custom_query_expressions(self, custom_query, custom_offsets): """ Generate query expressions for custom fields. it is assumed that custom fields are to be found in metadata doc and their offsets are provided. custom_query is a dict of key fields involving custom fields. """ custom_exprs = [] for key in custom_query: # for now we assume all custom query fields are SimpleDocFields custom_field = SimpleDocField(custom_query[key], custom_query[key], DATASET.c.metadata, False, offset=custom_offsets[key]) custom_exprs.append( fields.as_expression(custom_field, custom_query[key])) return custom_exprs