def METHOD_NAME(self, **query: QueryField) -> Iterator[Tuple[Product, Mapping[str, QueryField]]]:
    def listify(v):
        if isinstance(v, tuple):
            return list()
        elif isinstance(v, list):
            return v
        else:
            return [v]
    for prod in self.get_all():
        unmatched = query.copy()
        # Skip non-matched if user specified specific products/metadata_types
        if prod.name not in listify(unmatched.pop('product', prod.name)):
            continue
        if prod.metadata_type.name not in listify(unmatched.pop('metadata_type', prod.metadata_type.name)):
            continue
        # Check that all search keys match this product
        for key, value in list(unmatched.items()):
            field = prod.metadata_type.dataset_fields.get(key)
            if not field:
                # Product doesn't have this field - can't match
                break
            if not hasattr(field, 'extract'):
                # non-document/native field (??)
                continue
            if field.extract(prod.metadata_doc) is None:  # type: ignore[attr-defined]
                # Product has the field, but not defined in the type doc, so unmatchable
                continue
            expr = as_expression(field, value)
            if expr.evaluate(prod.metadata_doc):
                # matches
                unmatched.pop(key)
            else:
                # Doesn't match, skip to next product
                break
        else:
            yield prod, unmatched