From 7de0bb8ed4b508797e6895fa6cae25e395e5c54a Mon Sep 17 00:00:00 2001 From: Petr Jasek Date: Thu, 8 Dec 2022 17:45:17 +0100 Subject: [PATCH] fix filter conditions with like/startswith/endswith use `regex.search` instead of `regex.match` which is not looking for the whole thing to match but it can match anywhere in the value. we're adding `.*` before and after the regex, but that doesn't work with filters like `Foo|Bar|Baz` as those `.*` are only applied to the begging and then `Bar` would only match if it's the only content in the field. SDESK-6755 --- .../filter_condition/filter_condition_operator.py | 4 ++-- .../filter_condition/filter_condition_value.py | 2 +- tests/content_filters/filter_condition_tests.py | 11 ++++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/content_filters/filter_condition/filter_condition_operator.py b/apps/content_filters/filter_condition/filter_condition_operator.py index ba6031a9a6..0b46740b2e 100644 --- a/apps/content_filters/filter_condition/filter_condition_operator.py +++ b/apps/content_filters/filter_condition/filter_condition_operator.py @@ -109,7 +109,7 @@ def __init__(self, operator): self.elastic_operator = "query_string" def does_match(self, article_value, filter_value): - return filter_value.match(article_value) is None + return filter_value.search(article_value) is None def contains_not(self): return True @@ -174,7 +174,7 @@ def __init__(self, operator): self.elastic_operator = "query_string" def does_match(self, article_value, filter_value): - return filter_value.match(article_value) is not None + return filter_value.search(article_value) is not None class MatchOperator(FilterConditionOperator): diff --git a/apps/content_filters/filter_condition/filter_condition_value.py b/apps/content_filters/filter_condition/filter_condition_value.py index 17bcdafb06..68ec2d44b6 100644 --- a/apps/content_filters/filter_condition/filter_condition_value.py +++ b/apps/content_filters/filter_condition/filter_condition_value.py @@ -21,7 +21,7 @@ class FilterConditionValue: FilterConditionOperatorsEnum.startswith: "^{}", FilterConditionOperatorsEnum.like: ".*{}.*", FilterConditionOperatorsEnum.notlike: ".*{}.*", - FilterConditionOperatorsEnum.endswith: ".*{}", + FilterConditionOperatorsEnum.endswith: ".*{}$", } elastic_mapper = { diff --git a/tests/content_filters/filter_condition_tests.py b/tests/content_filters/filter_condition_tests.py index f7da3d8200..f1af3fd36f 100644 --- a/tests/content_filters/filter_condition_tests.py +++ b/tests/content_filters/filter_condition_tests.py @@ -465,7 +465,7 @@ def test_get_mongo_value(self): self.assertEqual(f.value.get_mongo_value(f.field), re.compile("^test", re.IGNORECASE)) f = FilterCondition("headline", "endswith", "test") - self.assertEqual(f.value.get_mongo_value(f.field), re.compile(".*test", re.IGNORECASE)) + self.assertEqual(f.value.get_mongo_value(f.field), re.compile(".*test$", re.IGNORECASE)) def test_does_match_with_eq(self): f = FilterCondition("urgency", "eq", "1") @@ -558,6 +558,15 @@ def test_does_match_with_like_partial(self): self.assertFalse(f.does_match(self.articles[4])) self.assertFalse(f.does_match(self.articles[5])) + def test_does_match_with_like_complex(self): + f = FilterCondition("headline", "like", "Foo|Bar|Baz|Test Multiword") + self.assertTrue(f.does_match({"headline": "Bar"})) + self.assertTrue(f.does_match({"headline": "Bar Something"})) + self.assertTrue(f.does_match({"headline": "Something Bar"})) + self.assertTrue(f.does_match({"headline": "Something Baz"})) + self.assertFalse(f.does_match({"headline": "Something Test"})) + self.assertTrue(f.does_match({"headline": "Something Test Multiword"})) + def test_does_match_with_startswith_filter(self): f = FilterCondition("headline", "startswith", "Sto") self.assertTrue(f.does_match(self.articles[0]))