Skip to content

Commit

Permalink
[SDESK-380] Add 'Place' to the list of criteria fields available for …
Browse files Browse the repository at this point in the history
…Content Filters
  • Loading branch information
marwoodandrew committed Dec 5, 2016
1 parent 398a781 commit fe14aa9
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 13 deletions.
8 changes: 6 additions & 2 deletions apps/content_filters/filter_condition/filter_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from apps.content_filters.filter_condition.filter_condition_field import FilterConditionField
from apps.content_filters.filter_condition.filter_condition_value import FilterConditionValue
from apps.content_filters.filter_condition.filter_condition_operator import \
FilterConditionOperator, NotInOperator, NotLikeOperator
FilterConditionOperator, NotInOperator, NotLikeOperator, MatchOperator
import json


class FilterCondition:
Expand All @@ -36,7 +37,10 @@ def get_elastic_query(self):
field = self.field.get_entity_name()
operator = self.operator.get_elastic_operator()
value, field = self.value.get_elastic_value(self.field)
return {operator: {field: value}}
if isinstance(self.operator, MatchOperator):
return json.loads(operator.format(field, value))
else:
return {operator: {field: value}}

def does_match(self, article):

Expand Down
15 changes: 14 additions & 1 deletion apps/content_filters/filter_condition/filter_condition_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class FilterConditionFieldsEnum(Enum):
headline = 12,
body_html = 13,
stage = 14,
ednote = 15
ednote = 15,
place = 16


class FilterConditionField:
Expand All @@ -47,6 +48,8 @@ def factory(field):
return FilterConditionSubjectField(field)
elif FilterConditionFieldsEnum[field] == FilterConditionFieldsEnum.urgency:
return FilterConditionUrgencyField(field)
elif FilterConditionFieldsEnum[field] == FilterConditionFieldsEnum.place:
return FilterConditionPlaceField(field)
else:
return FilterConditionField(field)

Expand Down Expand Up @@ -146,3 +149,13 @@ def is_in_article(self, article):

def get_value(self, article):
return str(article.get('flags', {}).get('marked_for_sms'))


class FilterConditionPlaceField(FilterConditionField):
def __init__(self, field):
self.field = FilterConditionFieldsEnum.place
self.entity_name = 'place.qcode'
self.field_type = str

def get_value(self, article):
return [c['qcode'] for c in article[self.field.name]]
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class FilterConditionOperatorsEnum(Enum):
like = 3,
notlike = 4,
startswith = 5,
endswith = 6
endswith = 6,
match = 7


class FilterConditionOperator:
Expand All @@ -30,6 +31,8 @@ def factory(operator):
return NotInOperator(operator)
elif operator == FilterConditionOperatorsEnum.notlike.name:
return NotLikeOperator(operator)
elif operator == FilterConditionOperatorsEnum.match.name:
return MatchOperator(operator)
else:
return RegexOperator(operator)

Expand Down Expand Up @@ -97,3 +100,16 @@ def __init__(self, operator):

def does_match(self, article_value, filter_value):
return filter_value.match(article_value) is not None


class MatchOperator(FilterConditionOperator):
def __init__(self, operator):
self.operator = FilterConditionOperatorsEnum[operator]
self.mongo_operator = '$in'
self.elastic_operator = '{{"query_string": {{"{}":"{}"}}}}'

def does_match(self, article_value, filter_value):
if isinstance(article_value, list):
return any([self.get_lower_case(v) in map(self.get_lower_case, filter_value) for v in article_value])
else:
return self.get_lower_case(article_value) in map(self.get_lower_case, filter_value)
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ def get(self, req, lookup):
'operators': ['in', 'nin'],
'values': values['sms'],
'value_field': 'name'
},
{'field': 'place',
'operators': ['match'],
'values': values['place'],
'value_field': 'qcode'
}])

def _get_field_values(self):
Expand All @@ -110,6 +115,7 @@ def _get_field_values(self):
values['desk'] = list(get_resource_service('desks').get(None, {}))
values['stage'] = self._get_stage_field_values(values['desk'])
values['sms'] = [{'qcode': 0, 'name': 'False'}, {'qcode': 1, 'name': 'True'}]
values['place'] = vocabularies_resource.find_one(req=None, _id='locators')['items']
return values

def _get_stage_field_values(self, desks):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class FilterConditionResource(Resource):
'subject',
'desk',
'stage',
'sms'],
'sms',
'place'],
},
'operator': {
'type': 'string',
Expand All @@ -46,7 +47,8 @@ class FilterConditionResource(Resource):
'like',
'notlike',
'startswith',
'endswith'],
'endswith',
'match'],
'empty': False,
'nullable': False,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class FilterConditionValue:
elastic_mapper = {FilterConditionOperatorsEnum.startswith: '{}:{}*',
FilterConditionOperatorsEnum.like: '{}:*{}*',
FilterConditionOperatorsEnum.notlike: '{}:*{}*',
FilterConditionOperatorsEnum.endswith: '{}:*{}'}
FilterConditionOperatorsEnum.endswith: '{}:*{}',
FilterConditionOperatorsEnum.match: '{}:{}'}

def __init__(self, operator, value):
self.operator = operator
Expand Down
40 changes: 34 additions & 6 deletions apps/content_filters/filter_condition/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def setUp(self):
'parent': '05005000'}], 'state': 'fetched'},
{'_id': '9', 'state': 'fetched', 'anpa_category':
[{'qcode': 'a', 'name': 'Aus News'}]},
{'_id': '10', 'body_html': '<p>Mention<p>'}]
{'_id': '10', 'body_html': '<p>Mention<p>'},
{'_id': '11', 'place': [{'qcode': 'NSW', 'name': 'NSW'}], 'state': 'fetched'}]

self.app.data.insert('archive', self.articles)

Expand Down Expand Up @@ -91,6 +92,14 @@ def _setup_elastic_args(self, elastic_translation, search_type='filter'):
'filter': {
'bool': {
'should': [elastic_translation]}}}}})}
elif search_type == 'match':
self.req.args = {'source': json.dumps({'query': {
'filtered': {
'query': {
'bool': {
'should': [{
'bool': {
'must': [elastic_translation]}}]}}}}})}

def test_mongo_using_genre_filter_complete_string(self):
f = FilterCondition('genre', 'in', 'Sidebar')
Expand All @@ -116,7 +125,7 @@ def test_mongo_using_desk_filter_nin(self):
with self.app.app_context():
docs = get_resource_service('archive').\
get_from_mongo(req=self.req, lookup=query)
self.assertEqual(9, docs.count())
self.assertEqual(10, docs.count())

def test_mongo_using_sms_filter_with_is(self):
f = FilterCondition('sms', 'in', 'true')
Expand Down Expand Up @@ -196,7 +205,7 @@ def test_mongo_using_notlike_filter(self):
with self.app.app_context():
docs = get_resource_service('archive').\
get_from_mongo(req=self.req, lookup=query)
self.assertEqual(9, docs.count())
self.assertEqual(10, docs.count())
doc_ids = [d['_id'] for d in docs]
self.assertTrue('2' not in doc_ids)

Expand All @@ -216,7 +225,7 @@ def test_mongo_using_notin_filter(self):
with self.app.app_context():
docs = get_resource_service('archive').\
get_from_mongo(req=self.req, lookup=query)
self.assertEqual(7, docs.count())
self.assertEqual(8, docs.count())
doc_ids = [d['_id'] for d in docs]
self.assertTrue('1' in doc_ids)
self.assertTrue('2' in doc_ids)
Expand Down Expand Up @@ -278,7 +287,7 @@ def test_elastic_using_nin_filter(self):
with self.app.app_context():
self._setup_elastic_args(query, 'not')
docs = get_resource_service('archive').get(req=self.req, lookup=None)
self.assertEqual(7, docs.count())
self.assertEqual(8, docs.count())
doc_ids = [d['_id'] for d in docs]
self.assertTrue('6' in doc_ids)
self.assertTrue('5' in doc_ids)
Expand All @@ -300,7 +309,7 @@ def test_elastic_using_notlike_filter(self):
with self.app.app_context():
self._setup_elastic_args(query, 'not')
docs = get_resource_service('archive').get(req=self.req, lookup=None)
self.assertEqual(8, docs.count())
self.assertEqual(9, docs.count())
doc_ids = [d['_id'] for d in docs]
self.assertTrue('2' not in doc_ids)

Expand Down Expand Up @@ -524,3 +533,22 @@ def test_check_similar(self):
self.assertTrue(len(f.check_similar(filter_condition4)) == 3)
self.assertTrue(len(f.check_similar(filter_condition5)) == 1)
self.assertTrue(len(f.check_similar(filter_condition6)) == 1)

def test_mongo_using_place_filter_complete_string(self):
f = FilterCondition('place', 'in', 'NSW')
query = f.get_mongo_query()
with self.app.app_context():
docs = get_resource_service('archive'). \
get_from_mongo(req=self.req, lookup=query)
self.assertEqual(1, docs.count())
self.assertEqual('11', docs[0]['_id'])

def test_elastic_using_place_filter_complete_string(self):
f = FilterCondition('place', 'match', 'NSW')
query = f.get_elastic_query()
with self.app.app_context():
self._setup_elastic_args(query, 'match')
docs = get_resource_service('archive').get(req=self.req, lookup=None)
doc_ids = [d['_id'] for d in docs]
self.assertEqual(1, docs.count())
self.assertTrue('11' in doc_ids)
8 changes: 8 additions & 0 deletions apps/prepopulate/data_init/vocabularies.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,13 @@
"items": [
{"is_active": true, "existing": "FIXME", "replacement": ""}
]
},
{
"_id": "locators",
"display_name": "Locators",
"type": "unmanageable",
"items": [
{"is_active": true, "name": "NSW", "qcode": "NSW"}
]
}
]

0 comments on commit fe14aa9

Please sign in to comment.