Skip to content
This repository has been archived by the owner on Jan 28, 2020. It is now read-only.

Commit

Permalink
Added capability to facet by missing Vocabulary terms in REST API search
Browse files Browse the repository at this point in the history
The facet for this must look like:
/api/v1/repositories/small/search/?selected_facets=_missing_:3_exact
  • Loading branch information
Giovanni Di Milia committed Sep 10, 2015
1 parent c0f8fa8 commit 29bd4f6
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 21 deletions.
81 changes: 79 additions & 2 deletions rest/tests/test_search.py
Expand Up @@ -235,8 +235,10 @@ def test_facets(self):
term1 = Term.objects.create(vocabulary=vocab, label='term1', weight=1)
term2 = Term.objects.create(vocabulary=vocab, label='term2', weight=1)

# getting two specific type of learning resources
resources = LearningResource.objects.filter(
course__repository__id=self.repo.id
course__repository__id=self.repo.id,
learning_resource_type__name='html'
).all()

resource1 = resources[0]
Expand Down Expand Up @@ -307,6 +309,77 @@ def test_facets(self):
)['count']
)

# Facets with missing counts for vocabularies
results = self.get_results()
facet_counts = results['facet_counts']
# No missing count for facets that are not vocabularies
self.assertEqual(
facet_counts['run']['facet'],
{'key': 'run', 'label': 'Run'}
)
self.assertEqual(
facet_counts['course']['facet'],
{'key': 'course', 'label': 'Course'}
)
self.assertEqual(
facet_counts['resource_type']['facet'],
{'key': 'resource_type', 'label': 'Item Type'}
)
# And missing count for vocabulary
# Note there are two learning resources tagged with
# terms at the beginning of this test
self.assertEqual(
facet_counts[str(vocab.id)]['facet'],
{
'key': str(vocab.id),
'label': vocab.name,
'missing_count': results['count'] - 2
}
)
# the missing count reflects the filtering
# both html LR have a term
results = self.get_results(
selected_facets=['resource_type_exact:html'])
facet_counts = results['facet_counts']
self.assertEqual(results['count'], 2)
self.assertEqual(
facet_counts[str(vocab.id)]['facet'],
{
'key': str(vocab.id),
'label': vocab.name,
'missing_count': 0
}
)
# no chapter LR has a term
results = self.get_results(
selected_facets=['resource_type_exact:chapter'])
facet_counts = results['facet_counts']
self.assertEqual(results['count'], 2)
self.assertEqual(
facet_counts[str(vocab.id)]['facet'],
{
'key': str(vocab.id),
'label': vocab.name,
'missing_count': 2
}
)
# filtering by missing vocabulary
results = self.get_results(
selected_facets=['_missing_:{0}_exact'.format(vocab.id)])
facet_counts = results['facet_counts']
self.assertEqual(results['count'], 17)
self.assertEqual(
facet_counts[str(vocab.id)],
{
'facet': {
'key': str(vocab.id),
'label': vocab.name,
'missing_count': 17
},
'values': []
}
)

# Facet count
facet_counts = self.get_results(
selected_facets=["{v}_exact:{t}".format(
Expand Down Expand Up @@ -353,7 +426,11 @@ def test_facets(self):
self.assertEqual(
facet_counts[str(vocab.id)],
{
'facet': {'key': str(vocab.id), 'label': vocab.name},
'facet': {
'key': str(vocab.id),
'label': vocab.name,
'missing_count': 0
},
'values': [{
'count': 1,
'key': str(term1.id),
Expand Down
54 changes: 35 additions & 19 deletions rest/views.py
Expand Up @@ -26,6 +26,7 @@
from celery.result import AsyncResult
from haystack.inputs import Exact
from haystack.query import SearchQuerySet
from statsd.defaults.django import statsd

from exporter.tasks import export_resources
from roles.permissions import GroupTypes, BaseGroupTypes
Expand Down Expand Up @@ -804,11 +805,30 @@ def get_queryset(self):

return queryset

def make_facet_counts(self, queryset):
def make_facet_counts(self, queryset): # pylint: disable=too-many-locals
"""
Facets on every facet available and provides a data structure
of facet count information ready for API use.
"""
def reformat(key, values, missing_count=None):
"""Convert tuples to dictionaries so we can use keys."""
reformatted = {
"facet": {
"key": str(key[0]),
"label": key[1]
},
"values": [
{
"label": value_label,
"key": str(value_key),
"count": count
} for value_key, value_label, count in values
]
}
if missing_count is not None:
reformatted["facet"]["missing_count"] = missing_count
return reformatted

for facet in ('course', 'run', 'resource_type'):
queryset = queryset.facet(facet)

Expand All @@ -819,7 +839,17 @@ def make_facet_counts(self, queryset):
queryset = queryset.facet(vocabulary.id)

facet_counts = queryset.facet_counts()
ret = get_vocabularies(facet_counts)
vocabs = get_vocabularies(facet_counts)

# return dictionary
ret_dict = {}

# process vocabularies
for key, values in vocabs.items():
missing_count = queryset.filter(
_missing_='{0}_exact'.format(key[0])).count()
ret_dict[key[0]] = reformat(
key, values, missing_count=missing_count)

# Reformat facet_counts to match term counts.
for key, label in (
Expand All @@ -832,25 +862,11 @@ def make_facet_counts(self, queryset):
in facet_counts['fields'][key]]
else:
values = []
ret[(key, label)] = values
ret_dict[key] = reformat((key, label), values)

def reformat(key, values):
"""Convert tuples to dictionaries so we can use keys."""
return {
"facet": {"key": str(key[0]), "label": key[1]},
"values": [
{
"label": value_label,
"key": str(value_key),
"count": count
} for value_key, value_label, count in values
]
}
return {
str(key[0]): reformat(key, values)
for key, values in ret.items()
}
return ret_dict

@statsd.timer('lore.rest.repository_search_list')
def list(self, *args, **kwargs): # pylint: disable=unused-argument
"""
Returns response object containing search results, including
Expand Down

0 comments on commit 29bd4f6

Please sign in to comment.