Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
course-discovery
Commits
ae40c8c2
Commit
ae40c8c2
authored
Mar 01, 2017
by
Anthony Mangano
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add custom endpoint that returns distinct hit and facet counts
ECOM-6815
parent
a4495712
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
125 additions
and
1 deletions
+125
-1
course_discovery/apps/api/v1/tests/test_views/test_search.py
+1
-1
course_discovery/apps/edx_catalog_extensions/api/__init__.py
+0
-0
course_discovery/apps/edx_catalog_extensions/api/serializers.py
+83
-0
course_discovery/apps/edx_catalog_extensions/api/urls.py
+5
-0
course_discovery/apps/edx_catalog_extensions/api/v1/__init__.py
+0
-0
course_discovery/apps/edx_catalog_extensions/api/v1/tests/__init__.py
+0
-0
course_discovery/apps/edx_catalog_extensions/api/v1/tests/test_views.py
+0
-0
course_discovery/apps/edx_catalog_extensions/api/v1/urls.py
+10
-0
course_discovery/apps/edx_catalog_extensions/api/v1/views.py
+15
-0
course_discovery/apps/edx_catalog_extensions/urls.py
+5
-0
course_discovery/urls.py
+6
-0
No files found.
course_discovery/apps/api/v1/tests/test_views/test_search.py
View file @
ae40c8c2
...
...
@@ -313,7 +313,7 @@ class CourseRunSearchViewSetTests(DefaultPartnerMixin, SerializationMixin, Login
@ddt.ddt
class
AggregateSearchViewSet
(
DefaultPartnerMixin
,
SerializationMixin
,
LoginMixin
,
ElasticsearchTestMixin
,
class
AggregateSearchViewSet
Tests
(
DefaultPartnerMixin
,
SerializationMixin
,
LoginMixin
,
ElasticsearchTestMixin
,
SynonymTestMixin
,
APITestCase
):
path
=
reverse
(
'api:v1:search-all-facets'
)
...
...
course_discovery/apps/edx_catalog_extensions/api/__init__.py
0 → 100644
View file @
ae40c8c2
course_discovery/apps/edx_catalog_extensions/api/serializers.py
0 → 100644
View file @
ae40c8c2
# pylint: disable=abstract-method
from
drf_haystack.fields
import
FacetDictField
,
FacetListField
from
drf_haystack.serializers
import
FacetFieldSerializer
from
rest_framework
import
serializers
from
rest_framework.fields
import
DictField
from
course_discovery.apps.api.serializers
import
AggregateFacetSearchSerializer
,
QueryFacetFieldSerializer
class
DistinctCountsAggregateFacetSearchSerializer
(
AggregateFacetSearchSerializer
):
""" Custom AggregateFacetSearchSerializer which includes distinct hit and facet counts."""
def
get_fields
(
self
):
""" Return the field_mapping needed for serializing the data."""
# Re-implement the logic from the superclass methods, but make sure to handle field and query facets properly.
# https://github.com/edx/course-discovery/blob/master/course_discovery/apps/api/serializers.py#L950
# https://github.com/inonit/drf-haystack/blob/master/drf_haystack/serializers.py#L373
field_data
=
self
.
instance
.
pop
(
'fields'
,
{})
query_data
=
self
.
format_query_facet_data
(
self
.
instance
.
pop
(
'queries'
,
{}))
field_mapping
=
super
(
DistinctCountsAggregateFacetSearchSerializer
,
self
)
.
get_fields
()
field_mapping
[
'fields'
]
=
FacetDictField
(
child
=
FacetListField
(
child
=
DistinctCountsFacetFieldSerializer
(
field_data
),
required
=
False
)
)
field_mapping
[
'queries'
]
=
DictField
(
query_data
,
child
=
DistinctCountsQueryFacetFieldSerializer
(),
required
=
False
)
if
self
.
serialize_objects
:
field_mapping
.
move_to_end
(
'objects'
)
self
.
instance
[
'fields'
]
=
field_data
self
.
instance
[
'queries'
]
=
query_data
return
field_mapping
def
get_objects
(
self
,
instance
):
""" Return the objects that should be serialized along with the facets."""
data
=
super
(
DistinctCountsAggregateFacetSearchSerializer
,
self
)
.
get_objects
(
instance
)
data
[
'distinct_count'
]
=
self
.
context
[
'objects'
]
.
distinct_count
()
return
data
def
format_query_facet_data
(
self
,
query_facet_counts
):
""" Format and return the query facet data so that it may be properly serialized."""
# Re-implement the logic from the superclass method, but make sure to handle changes to the raw query facet
# data and extract the distinct counts.
# https://github.com/edx/course-discovery/blob/master/course_discovery/apps/api/serializers.py#L966
query_data
=
{}
for
field
,
options
in
getattr
(
self
.
Meta
,
'field_queries'
,
{})
.
items
():
# pylint: disable=no-member
# The query facet data is expected to be formatted as a dictionary with fields mapping to a two-tuple
# containing count and distinct count.
count
,
distinct_count
=
query_facet_counts
.
get
(
field
,
(
0
,
0
))
if
count
:
query_data
[
field
]
=
{
'field'
:
field
,
'options'
:
options
,
'count'
:
count
,
'distinct_count'
:
distinct_count
,
}
return
query_data
class
DistinctCountsFacetFieldSerializer
(
FacetFieldSerializer
):
""" Custom FacetFieldSerializer which includes distinct counts."""
distinct_count
=
serializers
.
SerializerMethodField
()
def
get_distinct_count
(
self
,
instance
):
""" Return the distinct count for this facet."""
# The instance is expected to be formatted as a three tuple containing the field name, normal count and
# distinct count. This is consistent with the superclass implementation here:
# https://github.com/inonit/drf-haystack/blob/master/drf_haystack/serializers.py#L321
count
=
instance
[
2
]
return
serializers
.
IntegerField
(
read_only
=
True
)
.
to_representation
(
count
)
class
DistinctCountsQueryFacetFieldSerializer
(
QueryFacetFieldSerializer
):
""" Custom QueryFacetFieldSerializer which includes distinct counts."""
distinct_count
=
serializers
.
SerializerMethodField
()
def
get_distinct_count
(
self
,
instance
):
""" Return the distinct count for this facet."""
count
=
instance
[
'distinct_count'
]
return
serializers
.
IntegerField
(
read_only
=
True
)
.
to_representation
(
count
)
course_discovery/apps/edx_catalog_extensions/api/urls.py
0 → 100644
View file @
ae40c8c2
from
django.conf.urls
import
include
,
url
urlpatterns
=
[
url
(
r'^v1/'
,
include
(
'course_discovery.apps.edx_catalog_extensions.api.v1.urls'
,
namespace
=
'v1'
)),
]
course_discovery/apps/edx_catalog_extensions/api/v1/__init__.py
0 → 100644
View file @
ae40c8c2
course_discovery/apps/edx_catalog_extensions/api/v1/tests/__init__.py
0 → 100644
View file @
ae40c8c2
course_discovery/apps/edx_catalog_extensions/api/v1/tests/test_views.py
0 → 100644
View file @
ae40c8c2
This diff is collapsed.
Click to expand it.
course_discovery/apps/edx_catalog_extensions/api/v1/urls.py
0 → 100644
View file @
ae40c8c2
from
django.conf.urls
import
url
from
course_discovery.apps.edx_catalog_extensions.api.v1.views
import
DistinctCountsAggregateSearchViewSet
# Only expose the facets action of this view
distinct_facets_action
=
DistinctCountsAggregateSearchViewSet
.
as_view
({
'get'
:
'facets'
})
urlpatterns
=
[
url
(
r'^search/all/facets'
,
distinct_facets_action
,
name
=
'search-all-facets'
)
]
course_discovery/apps/edx_catalog_extensions/api/v1/views.py
0 → 100644
View file @
ae40c8c2
from
course_discovery.apps.api.v1.views.search
import
AggregateSearchViewSet
from
course_discovery.apps.edx_catalog_extensions.api.serializers
import
DistinctCountsAggregateFacetSearchSerializer
from
course_discovery.apps.edx_haystack_extensions.distinct_counts.query
import
DistinctCountsSearchQuerySet
class
DistinctCountsAggregateSearchViewSet
(
AggregateSearchViewSet
):
""" Provides a facets action that can include distinct hit and facet counts in the response."""
# Custom serializer that includes distinct hit and facet counts.
facet_serializer_class
=
DistinctCountsAggregateFacetSearchSerializer
def
get_queryset
(
self
,
*
args
,
**
kwargs
):
""" Return the base Queryset to use to build up the search query."""
queryset
=
super
(
DistinctCountsAggregateSearchViewSet
,
self
)
.
get_queryset
(
*
args
,
**
kwargs
)
return
DistinctCountsSearchQuerySet
.
from_queryset
(
queryset
)
.
with_distinct_counts
(
'aggregation_key'
)
course_discovery/apps/edx_catalog_extensions/urls.py
0 → 100644
View file @
ae40c8c2
from
django.conf.urls
import
include
,
url
urlpatterns
=
[
url
(
r'^api/'
,
include
(
'course_discovery.apps.edx_catalog_extensions.api.urls'
,
namespace
=
'api'
)),
]
course_discovery/urls.py
View file @
ae40c8c2
...
...
@@ -50,6 +50,12 @@ urlpatterns = auth_urlpatterns + [
url
(
r'^taggit_autosuggest/'
,
include
(
'taggit_autosuggest.urls'
)),
]
# Add the catalog extension urls if edx_catalog_extensions is installed.
if
'course_discovery.apps.edx_catalog_extensions'
in
settings
.
INSTALLED_APPS
:
urlpatterns
.
append
(
url
(
r'^extensions/'
,
include
(
'course_discovery.apps.edx_catalog_extensions.urls'
,
namespace
=
'extensions'
))
)
if
settings
.
DEBUG
:
# pragma: no cover
# We need this url pattern to serve user uploaded assets according to
# https://docs.djangoproject.com/en/1.10/howto/static-files/#serving-files-uploaded-by-a-user-during-development
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment