Exemplo n.º 1
0
 def test_numeric_equality_negative(self):
     parsed = parse_xpath("number = -100.32")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "query": {
                         "match_all": {}
                     },
                     "filter": {
                         "and": ({
                             "term": {
                                 "case_properties.key.exact": "number"
                             }
                         }, {
                             "term": {
                                 "case_properties.value.exact": -100.32,
                             }
                         })
                     }
                 }
             }
         }
     }
     built_filter = build_filter_from_ast("domain", parsed)
     self.assertEqual(expected_filter, built_filter)
Exemplo n.º 2
0
 def test_numeric_comparison(self):
     parsed = parse_xpath("number <= '100.32'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "bool": {
                     "filter": [
                         {
                             "term": {
                                 "case_properties.key.exact": "number"
                             }
                         }
                     ],
                     "must": {
                         "range": {
                             "case_properties.value.numeric": {
                                 "lte": 100.32
                             }
                         }
                     }
                 }
             }
         }
     }
     self.checkQuery(expected_filter, build_filter_from_ast("domain", parsed), is_raw_query=True)
Exemplo n.º 3
0
    def test_nested_parent_lookups(self):
        parsed = parse_xpath("father/mother/house = 'Tyrell'")

        expected_filter = {
            "nested": {
                "path": "indices",
                "query": {
                    "filtered": {
                        "query": {
                            "match_all": {},
                        },
                        "filter": {
                            "and": ({
                                "terms": {
                                    "indices.referenced_id":
                                    [self.parent_case_id],
                                }
                            }, {
                                "term": {
                                    "indices.identifier": "father"
                                }
                            })
                        }
                    }
                }
            }
        }
        built_filter = build_filter_from_ast(self.domain, parsed)
        self.assertEqual(expected_filter, built_filter)
        self.assertEqual([self.child_case_id],
                         CaseSearchES().filter(built_filter).values_list(
                             '_id', flat=True))
Exemplo n.º 4
0
 def test_simple_filter(self):
     parsed = parse_xpath("name = 'farid'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "query": {
                         "match_all": {}
                     },
                     "filter": {
                         "and": ({
                             "term": {
                                 "case_properties.key.exact": "name"
                             }
                         }, {
                             "term": {
                                 "case_properties.value.exact": "farid"
                             }
                         })
                     }
                 }
             }
         }
     }
     built_filter = build_filter_from_ast("domain", parsed)
     self.assertEqual(expected_filter, built_filter)
Exemplo n.º 5
0
 def test_date_comparison(self):
     parsed = parse_xpath("dob >= '2017-02-12'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "bool": {
                     "filter": [
                         {
                             "term": {
                                 "case_properties.key.exact": "dob"
                             }
                         }
                     ],
                     "must": {
                         "range": {
                             "case_properties.value.date": {
                                 "gte": "2017-02-12"
                             }
                         }
                     }
                 }
             }
         }
     }
     self.checkQuery(expected_filter, build_filter_from_ast("domain", parsed), is_raw_query=True)
Exemplo n.º 6
0
 def test_numeric_comparison(self):
     parsed = parse_xpath("number <= '100.32'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "filter": {
                         "term": {
                             "case_properties.key.exact": "number"
                         }
                     },
                     "query": {
                         "range": {
                             "case_properties.value.numeric": {
                                 "lte": 100.32,
                             }
                         }
                     }
                 }
             }
         }
     }
     self.assertEqual(expected_filter,
                      build_filter_from_ast("domain", parsed))
Exemplo n.º 7
0
 def test_date_comparison(self):
     parsed = parse_xpath("dob >= '2017-02-12'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "filter": {
                         "term": {
                             "case_properties.key.exact": "dob"
                         }
                     },
                     "query": {
                         "range": {
                             "case_properties.value.date": {
                                 "gte": "2017-02-12",
                             }
                         }
                     }
                 }
             }
         }
     }
     self.assertEqual(expected_filter,
                      build_filter_from_ast("domain", parsed))
Exemplo n.º 8
0
    def test_parent_lookups(self):
        parsed = parse_xpath("father/name = 'Mace'")
        # return all the cases who's parent (relationship named 'father') has case property 'name' = 'Mace'

        expected_filter = {
            "nested": {
                "path": "indices",
                "query": {
                    "filtered": {
                        "query": {
                            "match_all": {
                            },
                        },
                        "filter": {
                            "and": (
                                {
                                    "terms": {
                                        "indices.referenced_id": [self.parent_case_id],
                                    }
                                },
                                {
                                    "term": {
                                        "indices.identifier": "father"
                                    }
                                }
                            )
                        }
                    }
                }
            }
        }
        built_filter = build_filter_from_ast(self.domain, parsed)
        self.assertEqual(expected_filter, built_filter)
        self.assertEqual([self.child_case_id], CaseSearchES().filter(built_filter).values_list('_id', flat=True))
Exemplo n.º 9
0
    def test_nested_parent_lookups(self):
        parsed = parse_xpath("father/mother/house = 'Tyrell'")

        expected_filter = {
            "nested": {
                "path": "indices",
                "query": {
                    "filtered": {
                        "query": {
                            "match_all": {
                            },
                        },
                        "filter": {
                            "and": (
                                {
                                    "terms": {
                                        "indices.referenced_id": [self.parent_case_id],
                                    }
                                },
                                {
                                    "term": {
                                        "indices.identifier": "father"
                                    }
                                }
                            )
                        }
                    }
                }
            }
        }
        built_filter = build_filter_from_ast(self.domain, parsed)
        self.assertEqual(expected_filter, built_filter)
        self.assertEqual([self.child_case_id], CaseSearchES().filter(built_filter).values_list('_id', flat=True))
Exemplo n.º 10
0
 def test_numeric_equality_negative(self):
     parsed = parse_xpath("number = -100.32")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "bool": {
                     "filter": [
                         {
                             "bool": {
                                 "filter": (
                                     {
                                         "term": {
                                             "case_properties.key.exact": "number"
                                         }
                                     },
                                     {
                                         "term": {
                                             "case_properties.value.exact": -100.32
                                         }
                                     }
                                 )
                             }
                         }
                     ],
                     "must": {
                         "match_all": {}
                     }
                 }
             }
         }
     }
     built_filter = build_filter_from_ast("domain", parsed)
     self.checkQuery(expected_filter, built_filter, is_raw_query=True)
Exemplo n.º 11
0
 def test_simple_filter(self):
     parsed = parse_xpath("name = 'farid'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "query": {
                         "match_all": {}
                     },
                     "filter": {
                         "and": (
                             {
                                 "term": {
                                     "case_properties.key.exact": "name"
                                 }
                             },
                             {
                                 "term": {
                                     "case_properties.value.exact": "farid"
                                 }
                             }
                         )
                     }
                 }
             }
         }
     }
     built_filter = build_filter_from_ast("domain", parsed)
     self.assertEqual(expected_filter, built_filter)
Exemplo n.º 12
0
    def test_simple_filter(self):
        parsed = parse_xpath("name = 'farid'")

        expected_filter = {
            "nested": {
                "path": "case_properties",
                "query": {
                    "bool": {
                        "filter": [
                            {
                                "bool": {
                                    "filter": (
                                        {
                                            "term": {
                                                "case_properties.key.exact": "name"
                                            }
                                        },
                                        {
                                            "term": {
                                                "case_properties.value.exact": "farid"
                                            }
                                        }
                                    )
                                }
                            }
                        ],
                        "must": {
                            "match_all": {}
                        }
                    }
                }
            }
        }
        built_filter = build_filter_from_ast("domain", parsed)
        self.checkQuery(expected_filter, built_filter, is_raw_query=True)
Exemplo n.º 13
0
    def test_parent_lookups(self):
        parsed = parse_xpath("father/name = 'Mace'")
        # return all the cases who's parent (relationship named 'father') has case property 'name' = 'Mace'

        expected_filter = {
            "nested": {
                "path": "indices",
                "query": {
                    "filtered": {
                        "query": {
                            "match_all": {},
                        },
                        "filter": {
                            "and": ({
                                "terms": {
                                    "indices.referenced_id":
                                    [self.parent_case_id],
                                }
                            }, {
                                "term": {
                                    "indices.identifier": "father"
                                }
                            })
                        }
                    }
                }
            }
        }
        built_filter = build_filter_from_ast(self.domain, parsed)
        self.assertEqual(expected_filter, built_filter)
        self.assertEqual([self.child_case_id],
                         CaseSearchES().filter(built_filter).values_list(
                             '_id', flat=True))
Exemplo n.º 14
0
    def xpath_query(self, domain, xpath):
        """Search for cases using an XPath predicate expression.

        Enter an arbitrary XPath predicate in the context of the case. Also supports related case lookups.
        e.g you can do things like:

        - case properties: "first_name = 'dolores' and last_name = 'abernathy'"
        - date ranges: "first_came_online >= '2017-08-12' or died <= '2020-11-15"
        - numeric ranges: "age >= 100 and height < 1.25"
        - related cases: "mother/first_name = 'maeve' or parent/parent/host/age = 13"
        """
        from corehq.apps.case_search.filter_dsl import (
            CaseFilterError,
            build_filter_from_ast,
        )

        try:
            return self.filter(
                build_filter_from_ast(domain, parse_xpath(xpath)))
        except (TypeError, RuntimeError) as e:
            raise CaseFilterError(
                _("Malformed search query: {search_query}").format(
                    search_query=e),
                None,
            )
Exemplo n.º 15
0
    def test_case_property_existence(self):
        parsed = parse_xpath("property != ''")
        expected_filter = {
            "not": {
                "or": (
                    {
                        "not": {
                            "nested": {
                                "path": "case_properties",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "match_all": {
                                            }
                                        },
                                        "filter": {
                                            "term": {
                                                "case_properties.key.exact": "property"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    {
                        "nested": {
                            "path": "case_properties",
                            "query": {
                                "filtered": {
                                    "query": {
                                        "match_all": {
                                        }
                                    },
                                    "filter": {
                                        "and": (
                                            {
                                                "term": {
                                                    "case_properties.key.exact": "property"
                                                }
                                            },
                                            {
                                                "term": {
                                                    "case_properties.value.exact": ""
                                                }
                                            }
                                        )
                                    }
                                }
                            }
                        }
                    }
                )
            }
        }

        self.assertEqual(expected_filter, build_filter_from_ast("domain", parsed))
Exemplo n.º 16
0
    def test_case_property_existence(self):
        parsed = parse_xpath("property != ''")
        expected_filter = {
            "not": {
                "or": (
                    {
                        "not": {
                            "nested": {
                                "path": "case_properties",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "match_all": {
                                            }
                                        },
                                        "filter": {
                                            "term": {
                                                "case_properties.key.exact": "property"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    {
                        "nested": {
                            "path": "case_properties",
                            "query": {
                                "filtered": {
                                    "query": {
                                        "match_all": {
                                        }
                                    },
                                    "filter": {
                                        "and": (
                                            {
                                                "term": {
                                                    "case_properties.key.exact": "property"
                                                }
                                            },
                                            {
                                                "term": {
                                                    "case_properties.value.exact": ""
                                                }
                                            }
                                        )
                                    }
                                }
                            }
                        }
                    }
                )
            }
        }

        self.assertEqual(expected_filter, build_filter_from_ast("domain", parsed))
Exemplo n.º 17
0
    def test_self_reference(self):
        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("name = other_property"))

        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("name > other_property"))

        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("parent/name > other_property"))
Exemplo n.º 18
0
    def test_self_reference(self):
        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("name = other_property"))

        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("name > other_property"))

        with self.assertRaises(CaseFilterError):
            build_filter_from_ast(None, parse_xpath("parent/name > other_property"))
Exemplo n.º 19
0
 def test_date_comparison(self):
     parsed = parse_xpath("dob >= '2017-02-12'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "filter": {
                         "term": {
                             "case_properties.key.exact": "dob"
                         }
                     },
                     "query": {
                         "range": {
                             "case_properties.value.date": {
                                 "gte": "2017-02-12",
                             }
                         }
                     }
                 }
             }
         }
     }
     self.assertEqual(expected_filter, build_filter_from_ast("domain", parsed))
Exemplo n.º 20
0
 def test_numeric_comparison(self):
     parsed = parse_xpath("number <= '100.32'")
     expected_filter = {
         "nested": {
             "path": "case_properties",
             "query": {
                 "filtered": {
                     "filter": {
                         "term": {
                             "case_properties.key.exact": "number"
                         }
                     },
                     "query": {
                         "range": {
                             "case_properties.value.numeric": {
                                 "lte": 100.32,
                             }
                         }
                     }
                 }
             }
         }
     }
     self.assertEqual(expected_filter, build_filter_from_ast("domain", parsed))
Exemplo n.º 21
0
    def test_nested_filter(self):
        parsed = parse_xpath("(name = 'farid' or name = 'leila') and dob <= '2017-02-11'")
        expected_filter = {
            "and": (
                {
                    "or": (
                        {
                            "nested": {
                                "path": "case_properties",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "match_all": {
                                            }
                                        },
                                        "filter": {
                                            "and": (
                                                {
                                                    "term": {
                                                        "case_properties.key.exact": "name"
                                                    }
                                                },
                                                {
                                                    "term": {
                                                        "case_properties.value.exact": "farid"
                                                    }
                                                }
                                            )
                                        }
                                    }
                                }
                            }
                        },
                        {
                            "nested": {
                                "path": "case_properties",
                                "query": {
                                    "filtered": {
                                        "query": {
                                            "match_all": {
                                            }
                                        },
                                        "filter": {
                                            "and": (
                                                {
                                                    "term": {
                                                        "case_properties.key.exact": "name"
                                                    }
                                                },
                                                {
                                                    "term": {
                                                        "case_properties.value.exact": "leila"
                                                    }
                                                }
                                            )
                                        }
                                    }
                                }
                            }
                        }
                    )
                },
                {
                    "nested": {
                        "path": "case_properties",
                        "query": {
                            "filtered": {
                                "filter": {
                                    "term": {
                                        "case_properties.key.exact": "dob"
                                    }
                                },
                                "query": {
                                    "range": {
                                        "case_properties.value.date": {
                                            "lte": "2017-02-11"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            )
        }

        built_filter = build_filter_from_ast("domain", parsed)
        self.assertEqual(expected_filter, built_filter)
Exemplo n.º 22
0
    def test_nested_filter(self):
        parsed = parse_xpath("(name = 'farid' or name = 'leila') and dob <= '2017-02-11'")
        expected_filter = {
            "bool": {
                "filter": [
                    {
                        "bool": {
                            "should": [
                                {
                                    "nested": {
                                        "path": "case_properties",
                                        "query": {
                                            "bool": {
                                                "filter": [
                                                    {
                                                        "bool": {
                                                            "filter": [
                                                                {
                                                                    "term": {
                                                                        "case_properties.key.exact": "name"
                                                                    }
                                                                },
                                                                {
                                                                    "term": {
                                                                        "case_properties.value.exact": "farid"
                                                                    }
                                                                }
                                                            ]
                                                        }
                                                    }
                                                ],
                                                "must": {
                                                    "match_all": {}
                                                }
                                            }
                                        }
                                    }
                                },
                                {
                                    "nested": {
                                        "path": "case_properties",
                                        "query": {
                                            "bool": {
                                                "filter": [
                                                    {
                                                        "bool": {
                                                            "filter": [
                                                                {
                                                                    "term": {
                                                                        "case_properties.key.exact": "name"
                                                                    }
                                                                },
                                                                {
                                                                    "term": {
                                                                        "case_properties.value.exact": "leila"
                                                                    }
                                                                }
                                                            ]
                                                        }
                                                    }
                                                ],
                                                "must": {
                                                    "match_all": {}
                                                }
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    {
                        "nested": {
                            "path": "case_properties",
                            "query": {
                                "bool": {
                                    "filter": [
                                        {
                                            "term": {
                                                "case_properties.key.exact": "dob"
                                            }
                                        }
                                    ],
                                    "must": {
                                        "range": {
                                            "case_properties.value.date": {
                                                "lte": "2017-02-11"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                ]
            }
        }

        built_filter = build_filter_from_ast("domain", parsed)
        self.checkQuery(expected_filter, built_filter, is_raw_query=True)
Exemplo n.º 23
0
    def test_case_property_existence(self):
        parsed = parse_xpath("property != ''")
        expected_filter = {
            "bool": {
                "must_not": {
                    "bool": {
                        "should": [
                            {
                                "bool": {
                                    "must_not": {
                                        "nested": {
                                            "path": "case_properties",
                                            "query": {
                                                "bool": {
                                                    "filter": [
                                                        {
                                                            "term": {
                                                                "case_properties.key.exact": "property"
                                                            }
                                                        }
                                                    ],
                                                    "must": {
                                                        "match_all": {}
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            {
                                "nested": {
                                    "path": "case_properties",
                                    "query": {
                                        "bool": {
                                            "filter": [
                                                {
                                                    "bool": {
                                                        "filter": [
                                                            {
                                                                "term": {
                                                                    "case_properties.key.exact": "property"
                                                                }
                                                            },
                                                            {
                                                                "term": {
                                                                    "case_properties.value.exact": ""
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ],
                                            "must": {
                                                "match_all": {}
                                            }
                                        }
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }

        self.checkQuery(expected_filter, build_filter_from_ast("domain", parsed), is_raw_query=True)
Exemplo n.º 24
0
def not_(node, context):
    from corehq.apps.case_search.filter_dsl import build_filter_from_ast
    confirm_args_count(node, 1)
    return filters.NOT(build_filter_from_ast(node.args[0], context))
Exemplo n.º 25
0
def _get_parent_case_ids_matching_subcase_query(subcase_query, context):
    """Get a list of case IDs for cases that have a subcase with the given index identifier
    and matching the subcase predicate filter.

    Only cases with `[>,=] case_count_gt` subcases will be returned.
    """
    # TODO: validate that the subcase filter doesn't contain any ancestor filtering
    from corehq.apps.case_search.filter_dsl import (
        MAX_RELATED_CASES,
        build_filter_from_ast,
    )

    if subcase_query.subcase_filter:
        subcase_filter = build_filter_from_ast(subcase_query.subcase_filter, context)
    else:
        subcase_filter = filters.match_all()

    index_identifier_filter = filters.term('indices.identifier', subcase_query.index_identifier)
    index_query = queries.nested(
        'indices',
        queries.filtered(
            queries.match_all(),
            filters.AND(
                index_identifier_filter,
                filters.NOT(filters.term('indices.referenced_id', ''))  # exclude deleted indices
            )
        )
    )
    es_query = (
        CaseSearchES().domain(context.domain)
        .filter(index_query)
        .filter(subcase_filter)
        .aggregation(
            aggregations.NestedAggregation(
                'indices', 'indices',
            ).aggregation(
                aggregations.FilterAggregation(
                    'matching_indices', index_identifier_filter
                ).aggregation(
                    aggregations.TermsAggregation(
                        'referenced_id', 'indices.referenced_id'
                    )
                )
            )
        )
    )

    if es_query.count() > MAX_RELATED_CASES:
        from ..exceptions import TooManyRelatedCasesError
        raise TooManyRelatedCasesError(
            _("The related case lookup you are trying to perform would return too many cases"),
            serialize(subcase_query.subcase_filter)
        )

    counts_by_parent_id = es_query.run().aggregations.indices.matching_indices.referenced_id.counts_by_bucket()
    if subcase_query.op == '>' and subcase_query.count <= 0:
        return list(counts_by_parent_id)

    return [
        case_id for case_id, count in counts_by_parent_id.items() if subcase_query.filter_count(count)
    ]
Exemplo n.º 26
0
    def test_nested_filter(self):
        parsed = parse_xpath(
            "(name = 'farid' or name = 'leila') and dob <= '2017-02-11'")
        expected_filter = {
            "and": ({
                "or": ({
                    "nested": {
                        "path": "case_properties",
                        "query": {
                            "filtered": {
                                "query": {
                                    "match_all": {}
                                },
                                "filter": {
                                    "and": ({
                                        "term": {
                                            "case_properties.key.exact": "name"
                                        }
                                    }, {
                                        "term": {
                                            "case_properties.value.exact":
                                            "farid"
                                        }
                                    })
                                }
                            }
                        }
                    }
                }, {
                    "nested": {
                        "path": "case_properties",
                        "query": {
                            "filtered": {
                                "query": {
                                    "match_all": {}
                                },
                                "filter": {
                                    "and": ({
                                        "term": {
                                            "case_properties.key.exact": "name"
                                        }
                                    }, {
                                        "term": {
                                            "case_properties.value.exact":
                                            "leila"
                                        }
                                    })
                                }
                            }
                        }
                    }
                })
            }, {
                "nested": {
                    "path": "case_properties",
                    "query": {
                        "filtered": {
                            "filter": {
                                "term": {
                                    "case_properties.key.exact": "dob"
                                }
                            },
                            "query": {
                                "range": {
                                    "case_properties.value.date": {
                                        "lte": "2017-02-11"
                                    }
                                }
                            }
                        }
                    }
                }
            })
        }

        built_filter = build_filter_from_ast("domain", parsed)
        self.assertEqual(expected_filter, built_filter)
Exemplo n.º 27
0
 def _check(xpath, error_msg):
     with assert_raises_regex(XPathFunctionException, error_msg):
         parsed = parse_xpath(xpath)
         build_filter_from_ast(parsed, SearchFilterContext("mydomain"))