From 8e7078dd3ebd0e024b2dd5f4a62cc224cafaee00 Mon Sep 17 00:00:00 2001 From: Matthew Evans Date: Fri, 6 Mar 2020 18:57:35 +0000 Subject: [PATCH] Use $nor when $or -> $not chain is found --- optimade/filtertransformers/mongo.py | 3 ++ tests/filtertransformers/test_mongo.py | 48 ++++++++++++-------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/optimade/filtertransformers/mongo.py b/optimade/filtertransformers/mongo.py index fa379de161..510cd34c1e 100755 --- a/optimade/filtertransformers/mongo.py +++ b/optimade/filtertransformers/mongo.py @@ -92,6 +92,9 @@ def expression_phrase(self, arg): # without NOT return arg[0] + if list(arg[1].keys()) == ["$or"]: + return {"$nor": arg[1]["$or"]} + # with NOT # TODO: This implementation probably fails in the case of `"(" expression ")"` return {prop: {"$not": expr} for prop, expr in arg[1].items()} diff --git a/tests/filtertransformers/test_mongo.py b/tests/filtertransformers/test_mongo.py index ad05d0b4cf..49de5b81dd 100644 --- a/tests/filtertransformers/test_mongo.py +++ b/tests/filtertransformers/test_mongo.py @@ -114,30 +114,28 @@ def test_operators(self): self.assertEqual(self.transform("NOT a<3"), {"a": {"$not": {"$lt": 3}}}) # TODO: {'$not': {'$eq': 'Ti'}} can be simplified to {'$ne': 'Ti'} - # TODO: THIS IS NOT A VALID MONGO QUERY!!! We should switch to $nor, but - # that may break the defined optimade operator precendence self.assertEqual( self.transform( - 'NOT ( chemical_formula_hill = "Al" AND chemical_formula_anonymous = "A" OR ' - 'chemical_formula_anonymous = "H2O" AND NOT chemical_formula_hill = "Ti" )' + "NOT ( " + 'chemical_formula_hill = "Al" AND chemical_formula_anonymous = "A" OR ' + 'chemical_formula_anonymous = "H2O" AND NOT chemical_formula_hill = "Ti"' + ")" ), { - "$or": { - "$not": [ - { - "$and": [ - {"chemical_formula_hill": {"$eq": "Al"}}, - {"chemical_formula_anonymous": {"$eq": "A"}}, - ] - }, - { - "$and": [ - {"chemical_formula_anonymous": {"$eq": "H2O"}}, - {"chemical_formula_hill": {"$not": {"$eq": "Ti"}}}, - ] - }, - ] - } + "$nor": [ + { + "$and": [ + {"chemical_formula_hill": {"$eq": "Al"}}, + {"chemical_formula_anonymous": {"$eq": "A"}}, + ] + }, + { + "$and": [ + {"chemical_formula_anonymous": {"$eq": "H2O"}}, + {"chemical_formula_hill": {"$not": {"$eq": "Ti"}}}, + ] + }, + ] }, ) @@ -166,12 +164,10 @@ def test_operators(self): "$and": [ {"nelements": {"$gte": 10}}, { - "$or": { - "$not": [ - {"_exmpl_x": {"$ne": "Some string"}}, - {"_exmpl_a": {"$not": {"$eq": 7}}}, - ] - } + "$nor": [ + {"_exmpl_x": {"$ne": "Some string"}}, + {"_exmpl_a": {"$not": {"$eq": 7}}}, + ] }, ] },