Skip to content

Mongo

MongoTransformer (Transformer)

Support for grammar v0.10.1

__init__(self, mapper=None) special

Initialise the object, optionally loading in a resource mapper for use when post-processing.

Source code in optimade/filtertransformers/mongo.py
def __init__(self, mapper: BaseResourceMapper = None):
    """ Initialise the object, optionally loading in a
    resource mapper for use when post-processing.

    """
    self.mapper = mapper
    super().__init__()

non_string_value(self, value)

non_string_value: number | property

Source code in optimade/filtertransformers/mongo.py
@v_args(inline=True)
def non_string_value(self, value):
    """ non_string_value: number | property """
    # Note: Do nothing!
    return value

not_implemented_string(self, value)

not_implemented_string: value

Raise NotImplementedError. For further information, see Materials-Consortia/OPTIMADE issue 157: https://github.com/Materials-Consortia/OPTIMADE/issues/157

Source code in optimade/filtertransformers/mongo.py
@v_args(inline=True)
def not_implemented_string(self, value):
    """ not_implemented_string: value

    Raise NotImplementedError.
    For further information, see Materials-Consortia/OPTIMADE issue 157:
    https://github.com/Materials-Consortia/OPTIMADE/issues/157
    """
    raise NotImplementedError("Comparing strings is not yet implemented.")

postprocess(self, query)

Used to post-process the final parsed query.

Source code in optimade/filtertransformers/mongo.py
def postprocess(self, query):
    """ Used to post-process the final parsed query. """
    if self.mapper:
        # important to apply length alias before normal aliases
        query = self._apply_length_aliases(query)
        query = self._apply_aliases(query)

    query = self._apply_relationship_filtering(query)
    query = self._apply_length_operators(query)
    query = self._apply_unknown_or_null_filter(query)

    return query

transform(self, tree)

Transform the given tree, and return the final result

Source code in optimade/filtertransformers/mongo.py
def transform(self, tree):
    return self.postprocess(super().transform(tree))

recursive_postprocessing(filter_, condition, replacement)

Recursively descend into the query, checking each dictionary (contained in a list, or as an entry in another dictionary) for the condition passed. If the condition is true, apply the replacement to the dictionary.

Parameters:

Name Type Description Default
filter_ list/dict

the filter_ to process.

required
condition callable

a function that returns True if the replacement function should be applied. It should take as arguments the property and expression from the filter_, as would be returned by iterating over filter_.items().

required
replacement callable

a function that returns the processed dictionary. It should take as arguments the dictionary to modify, the property and the expression (as described above).

required

Examples:

For the simple case of replacing one field name with another, the following functions could be used:

def condition(prop, expr):
    return prop == "field_name_old"

def replacement(d, prop, expr):
    d["field_name_old"] = d.pop(prop)

filter_ = recursive_postprocessing(
    filter_, condition, replacement
)
Source code in optimade/filtertransformers/mongo.py
def recursive_postprocessing(filter_, condition, replacement):
    """ Recursively descend into the query, checking each dictionary
    (contained in a list, or as an entry in another dictionary) for
    the condition passed. If the condition is true, apply the
    replacement to the dictionary.

    Parameters:
        filter_ (list/dict): the filter_ to process.
        condition (callable): a function that returns True if the
            replacement function should be applied. It should take
            as arguments the property and expression from the filter_,
            as would be returned by iterating over `filter_.items()`.
        replacement (callable): a function that returns the processed
            dictionary. It should take as arguments the dictionary
            to modify, the property and the expression (as described
            above).

    Example:
        For the simple case of replacing one field name with
        another, the following functions could be used:

        ```python
        def condition(prop, expr):
            return prop == "field_name_old"

        def replacement(d, prop, expr):
            d["field_name_old"] = d.pop(prop)

        filter_ = recursive_postprocessing(
            filter_, condition, replacement
        )

        ```

    """
    if isinstance(filter_, list):
        result = [recursive_postprocessing(q, condition, replacement) for q in filter_]
        return result

    if isinstance(filter_, dict):
        # this could potentially lead to memory leaks if the filter_ is *heavily* nested
        _cached_filter = copy.deepcopy(filter_)
        for prop, expr in filter_.items():
            if condition(prop, expr):
                _cached_filter = replacement(_cached_filter, prop, expr)
            elif isinstance(expr, list):
                _cached_filter[prop] = [
                    recursive_postprocessing(q, condition, replacement) for q in expr
                ]
        return _cached_filter

    return filter_