Commit fdb50a23 authored by Mathieu Rodic's avatar Mathieu Rodic

[FEATURE] added metadata filtering capability in advanced charts

parent 3fa340d6
...@@ -75,6 +75,27 @@ class NodeNgramsQueries(APIView): ...@@ -75,6 +75,27 @@ class NodeNgramsQueries(APIView):
'century': lambda d: (d + datetime.timedelta(days=36600)).replace(day=1, month=1), 'century': lambda d: (d + datetime.timedelta(days=36600)).replace(day=1, month=1),
} }
_operators = {
'=': lambda field, value: (field == value),
'!=': lambda field, value: (field != value),
'<': lambda field, value: (field < value),
'>': lambda field, value: (field > value),
'<=': lambda field, value: (field <= value),
'>=': lambda field, value: (field >= value),
'in': lambda field, value: (or_(*tuple(field == x for x in value))),
'contains': lambda field, value: (field.contains(value)),
'doesnotcontain': lambda field, value: (not_(field.contains(value))),
'startswith': lambda field, value: (field.startswith(value)),
}
_converters = {
'float': float,
'int': int,
'datetime': lambda x: x + '2000-01-01 00:00:00Z'[len(x):],
'text': str,
'str': str,
}
def post(self, request, project_id): def post(self, request, project_id):
# example only # example only
...@@ -115,6 +136,12 @@ class NodeNgramsQueries(APIView): ...@@ -115,6 +136,12 @@ class NodeNgramsQueries(APIView):
}}, }},
# filtering # filtering
'filter': {'type': dict, 'default': {}, 'items': { 'filter': {'type': dict, 'default': {}, 'items': {
# filter by metadata
'hyperdata': {'type': list, 'default': [], 'items': {'type': dict, 'items': {
'key': {'type': str, 'range': self._operators.keys()},
'operator': {'type': str},
'value': {'type': str},
}}},
# filter by date # filter by date
'date': {'type': dict, 'items': { 'date': {'type': dict, 'items': {
'min': {'type': datetime.datetime}, 'min': {'type': datetime.datetime},
...@@ -170,6 +197,27 @@ class NodeNgramsQueries(APIView): ...@@ -170,6 +197,27 @@ class NodeNgramsQueries(APIView):
.join(Ngram, Ngram.id == Node_Ngram.ngram_id) .join(Ngram, Ngram.id == Node_Ngram.ngram_id)
.filter(Ngram.terms.in_(input['filter']['ngrams'])) .filter(Ngram.terms.in_(input['filter']['ngrams']))
) )
# build query: filter by metadata
if 'hyperdata' in input['filter']:
for h, hyperdata in enumerate(input['filter']['hyperdata']):
# get hyperdata in database
hyperdata_model = (session
.query(Hyperdata.id, Hyperdata.type)
.filter(Hyperdata.name == hyperdata['key'])
).first()
if hyperdata_model is None:
continue
hyperdata_id, hyperdata_type = hyperdata_model
# create alias and query it
NH = aliased(Node_Hyperdata)
NH_column = getattr(NH, 'value_' + hyperdata_type)
operator = self._operators[hyperdata['operator']]
value = self._converters[hyperdata_type](hyperdata['value'])
query_result = (query_result
.join(NH, NH.node_id == Node.id)
.filter(NH.hyperdata_id == hyperdata_id)
.filter(operator(NH_column, value))
)
# build result: prepare data # build result: prepare data
date_value_list = query_result.all() date_value_list = query_result.all()
if date_value_list: if date_value_list:
...@@ -206,4 +254,3 @@ class NodeNgramsQueries(APIView): ...@@ -206,4 +254,3 @@ class NodeNgramsQueries(APIView):
}, 201) }, 201)
elif input['format'] == 'csv': elif input['format'] == 'csv':
return CsvHttpResponse(sorted(result.items()), ('date', 'value'), 201) return CsvHttpResponse(sorted(result.items()), ('date', 'value'), 201)
...@@ -104,12 +104,18 @@ ...@@ -104,12 +104,18 @@
<li> <li>
<ul> <ul>
<li ng-repeat="hyperdata in hyperdataList"> <li ng-repeat="hyperdata in hyperdataList">
...where the value of ...where
<span ng-if="!hyperdata.operator">"{{ hyperdata.key }}"</span> <span ng-if="!hyperdata.operator &amp;&amp; (!hyperdata.values || !hyperdata.value)">"{{ hyperdata.key }}"</span>
<strong ng-if="hyperdata.operator">{{ hyperdata.key }}</strong> <strong ng-if="hyperdata.operator || (hyperdata.values &amp;&amp; hyperdata.value)">{{ hyperdata.key }}</strong>
<span ng-if="hyperdata.values">
is
<select ng-model="hyperdata.value" ng-options="value for value in hyperdata.values" ng-change="updateDataset()"></select>
</span>
<span ng-if="!hyperdata.values">
<select ng-model="hyperdata.operator" ng-options="operator.key as operator.label for operator in operators[hyperdata.type]"></select> <select ng-model="hyperdata.operator" ng-options="operator.key as operator.label for operator in operators[hyperdata.type]"></select>
<input type="text" ng-if="hyperdata.operator" ng-model="hyperdata.value" ng-change="updateDataset()" placeholder="type a value here..." /> <input type="text" ng-if="hyperdata.operator" ng-model="hyperdata.value" ng-change="updateDataset()" placeholder="type a value here..." />
</span>
</li> </li>
</ul> </ul>
</li> </li>
...@@ -155,4 +161,3 @@ ...@@ -155,4 +161,3 @@
{% endblock %} {% endblock %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment