Commit c0b56065 by Anthony Mangano

add migration to populate ElasticsearchBoostConfig

ECOM-6715
parent 9572627a
...@@ -46,7 +46,7 @@ class AffiliateWindowViewSetTests(ElasticsearchTestMixin, SerializationMixin, AP ...@@ -46,7 +46,7 @@ class AffiliateWindowViewSetTests(ElasticsearchTestMixin, SerializationMixin, AP
def test_affiliate_with_supported_seats(self): def test_affiliate_with_supported_seats(self):
""" Verify that endpoint returns course runs for verified and professional seats only. """ """ Verify that endpoint returns course runs for verified and professional seats only. """
with self.assertNumQueries(11): with self.assertNumQueries(8):
response = self.client.get(self.affiliate_url) response = self.client.get(self.affiliate_url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
...@@ -130,7 +130,7 @@ class AffiliateWindowViewSetTests(ElasticsearchTestMixin, SerializationMixin, AP ...@@ -130,7 +130,7 @@ class AffiliateWindowViewSetTests(ElasticsearchTestMixin, SerializationMixin, AP
# Superusers can view all catalogs # Superusers can view all catalogs
self.client.force_authenticate(superuser) self.client.force_authenticate(superuser)
with self.assertNumQueries(8): with self.assertNumQueries(5):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
......
...@@ -147,7 +147,7 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi ...@@ -147,7 +147,7 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi
for course_run in excluded_runs: for course_run in excluded_runs:
SeatFactory(course_run=course_run) SeatFactory(course_run=course_run)
with self.assertNumQueries(45): with self.assertNumQueries(42):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertListEqual(response.data['results'], self.serialize_catalog_course(courses, many=True)) self.assertListEqual(response.data['results'], self.serialize_catalog_course(courses, many=True))
...@@ -173,7 +173,7 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi ...@@ -173,7 +173,7 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi
url = reverse('api:v1:catalog-csv', kwargs={'id': self.catalog.id}) url = reverse('api:v1:catalog-csv', kwargs={'id': self.catalog.id})
with self.assertNumQueries(21): with self.assertNumQueries(18):
response = self.client.get(url) response = self.client.get(url)
course_run = self.serialize_catalog_flat_course_run(self.course_run) course_run = self.serialize_catalog_flat_course_run(self.course_run)
......
...@@ -136,7 +136,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -136,7 +136,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
query = 'title:Some random title' query = 'title:Some random title'
url = '{root}?q={query}'.format(root=reverse('api:v1:course_run-list'), query=query) url = '{root}?q={query}'.format(root=reverse('api:v1:course_run-list'), query=query)
with self.assertNumQueries(40): with self.assertNumQueries(37):
response = self.client.get(url) response = self.client.get(url)
actual_sorted = sorted(response.data['results'], key=lambda course_run: course_run['key']) actual_sorted = sorted(response.data['results'], key=lambda course_run: course_run['key'])
......
...@@ -146,7 +146,7 @@ class CourseViewSetTests(SerializationMixin, APITestCase): ...@@ -146,7 +146,7 @@ class CourseViewSetTests(SerializationMixin, APITestCase):
query = 'title:' + title query = 'title:' + title
url = '{root}?q={query}'.format(root=reverse('api:v1:course-list'), query=query) url = '{root}?q={query}'.format(root=reverse('api:v1:course-list'), query=query)
with self.assertNumQueries(62): with self.assertNumQueries(59):
response = self.client.get(url) response = self.client.get(url)
self.assertListEqual(response.data['results'], self.serialize_course(courses, many=True)) self.assertListEqual(response.data['results'], self.serialize_course(courses, many=True))
......
...@@ -20,7 +20,6 @@ from course_discovery.apps.course_metadata.models import CourseRun, Program, Pro ...@@ -20,7 +20,6 @@ from course_discovery.apps.course_metadata.models import CourseRun, Program, Pro
from course_discovery.apps.course_metadata.tests.factories import ( from course_discovery.apps.course_metadata.tests.factories import (
CourseFactory, CourseRunFactory, ProgramFactory, OrganizationFactory CourseFactory, CourseRunFactory, ProgramFactory, OrganizationFactory
) )
from course_discovery.apps.edx_haystack_extensions.models import ElasticsearchBoostConfig
class SerializationMixin: class SerializationMixin:
...@@ -208,7 +207,7 @@ class CourseRunSearchViewSetTests(DefaultPartnerMixin, SerializationMixin, Login ...@@ -208,7 +207,7 @@ class CourseRunSearchViewSetTests(DefaultPartnerMixin, SerializationMixin, Login
active_program = ProgramFactory(courses=[course_run.course], status=ProgramStatus.Active) active_program = ProgramFactory(courses=[course_run.course], status=ProgramStatus.Active)
ProgramFactory(courses=[course_run.course], status=program_status) ProgramFactory(courses=[course_run.course], status=program_status)
with self.assertNumQueries(11): with self.assertNumQueries(8):
response = self.get_search_response('software', faceted=False) response = self.get_search_response('software', faceted=False)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
...@@ -284,7 +283,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin ...@@ -284,7 +283,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertListEqual( self.assertListEqual(
response_data['objects']['results'], response_data['objects']['results'],
[self.serialize_course_run(course_run), self.serialize_program(program)] [self.serialize_program(program), self.serialize_course_run(course_run)]
) )
# Filter results by partner # Filter results by partner
...@@ -292,7 +291,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin ...@@ -292,7 +291,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertListEqual(response_data['objects']['results'], self.assertListEqual(response_data['objects']['results'],
[self.serialize_course_run(other_course_run), self.serialize_program(other_program)]) [self.serialize_program(other_program), self.serialize_course_run(other_course_run)])
def test_empty_query(self): def test_empty_query(self):
""" Verify, when the query (q) parameter is empty, the endpoint behaves as if the parameter """ Verify, when the query (q) parameter is empty, the endpoint behaves as if the parameter
...@@ -304,7 +303,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin ...@@ -304,7 +303,7 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertListEqual(response_data['objects']['results'], self.assertListEqual(response_data['objects']['results'],
[self.serialize_course_run(course_run), self.serialize_program(program)]) [self.serialize_program(program), self.serialize_course_run(course_run)])
@ddt.data('start', '-start') @ddt.data('start', '-start')
def test_results_ordered_by_start_date(self, ordering): def test_results_ordered_by_start_date(self, ordering):
...@@ -328,14 +327,6 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin ...@@ -328,14 +327,6 @@ class AggregateSearchViewSet(DefaultPartnerMixin, SerializationMixin, LoginMixin
class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin, LoginMixin, ElasticsearchTestMixin, class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin, LoginMixin, ElasticsearchTestMixin,
APITestCase): APITestCase):
path = reverse('api:v1:search-typeahead') path = reverse('api:v1:search-typeahead')
function_score = {
'functions': [
{'filter': {'term': {'pacing_type_exact': 'self_paced'}}, 'weight': 1.0},
{'filter': {'term': {'type_exact': 'MicroMasters'}}, 'weight': 1.0},
{'linear': {'start': {'origin': 'now', 'scale': '1d', 'decay': 0.95}}, 'weight': 5.0}
],
'boost': 1.0, 'score_mode': 'sum', 'boost_mode': 'sum',
}
def get_typeahead_response(self, query=None, partner=None): def get_typeahead_response(self, query=None, partner=None):
qs = '' qs = ''
...@@ -344,9 +335,6 @@ class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin, ...@@ -344,9 +335,6 @@ class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin,
qs = urllib.parse.urlencode(query_dict) qs = urllib.parse.urlencode(query_dict)
url = '{path}?{qs}'.format(path=self.path, qs=qs) url = '{path}?{qs}'.format(path=self.path, qs=qs)
config = ElasticsearchBoostConfig.get_solo()
config.function_score.update(self.function_score)
config.save()
return self.client.get(url) return self.client.get(url)
def test_typeahead(self): def test_typeahead(self):
...@@ -434,20 +422,20 @@ class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin, ...@@ -434,20 +422,20 @@ class TypeaheadSearchViewTests(DefaultPartnerMixin, TypeaheadSerializationMixin,
""" Verify micromasters are boosted over xseries.""" """ Verify micromasters are boosted over xseries."""
title = "micromasters" title = "micromasters"
ProgramFactory( ProgramFactory(
title=title + "1", title=title + "1", status=ProgramStatus.Active,
type=ProgramType.objects.get(name='XSeries'), partner=self.partner
)
ProgramFactory(
title=title + "2",
status=ProgramStatus.Active, status=ProgramStatus.Active,
type=ProgramType.objects.get(name='MicroMasters'), type=ProgramType.objects.get(name='MicroMasters'),
partner=self.partner partner=self.partner
) )
ProgramFactory(
title=title + "2", status=ProgramStatus.Active,
type=ProgramType.objects.get(name='XSeries'), partner=self.partner
)
response = self.get_typeahead_response(title) response = self.get_typeahead_response(title)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
response_data = response.json() response_data = response.json()
self.assertEqual(response_data['programs'][0]['type'], 'MicroMasters') self.assertEqual(response_data['programs'][0]['type'], 'MicroMasters')
self.assertEqual(response_data['programs'][0]['title'], title + "1") self.assertEqual(response_data['programs'][0]['title'], title + "2")
def test_start_date_boosting(self): def test_start_date_boosting(self):
""" Verify upcoming courses are boosted over past courses.""" """ Verify upcoming courses are boosted over past courses."""
......
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2017-01-18 18:26
from django.db import migrations
def create_or_update_config_record(apps, schema_editor):
"""Create or update the ElasticsearchBoostConfig record."""
# Get the model from the versioned app registry to ensure the correct version is used, as described in
# https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runpython
ElasticsearchBoostConfig = apps.get_model('edx_haystack_extensions', 'ElasticsearchBoostConfig')
ElasticsearchBoostConfig.objects.update_or_create(
# The `solo` library uses 1 for the PrimaryKey to create/lookup the singleton record
# See https://github.com/lazybird/django-solo/blob/1.1.2/solo/models.py
pk=1,
# These values were taken from production on January 20, 2017.
defaults={
'function_score': {
'boost_mode': 'sum',
'boost': 1.0,
'score_mode': 'sum',
'functions': [
{'filter': {'term': {'pacing_type_exact': 'self_paced'}}, 'weight': 1.0},
{'filter': {'term': {'type_exact': 'MicroMasters'}}, 'weight': 1.0},
{'linear': {'start': {'origin': 'now', 'decay': 0.95, 'scale': '1d'}}, 'weight': 5.0}
]
}
}
)
class Migration(migrations.Migration):
dependencies = [
('edx_haystack_extensions', '0001_squashed_0002_auto_20160826_1750'),
]
operations = [
migrations.RunPython(create_or_update_config_record, reverse_code=migrations.RunPython.noop)
]
...@@ -35,17 +35,11 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin): ...@@ -35,17 +35,11 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin):
'analyze_wildcard': True, 'analyze_wildcard': True,
'auto_generate_phrase_queries': True, 'auto_generate_phrase_queries': True,
} }
default_function_score = {
'function_score': { def _default_function_score(self):
'query': { function_score = {'function_score': ElasticsearchBoostConfig.get_solo().function_score}
'query_string': simple_query function_score['function_score']['query'] = {'query_string': self.simple_query}
}, return function_score
'functions': [],
'boost': 1.0,
'score_mode': 'multiply',
'boost_mode': 'multiply'
}
}
def test_build_search_kwargs_all_qs_with_filter(self): def test_build_search_kwargs_all_qs_with_filter(self):
with patch.object(BaseSearchBackend, 'build_models_list', return_value=['course_metadata.course']): with patch.object(BaseSearchBackend, 'build_models_list', return_value=['course_metadata.course']):
...@@ -59,7 +53,7 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin): ...@@ -59,7 +53,7 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin):
kwargs = self.backend.build_search_kwargs(self.specific_query_string) kwargs = self.backend.build_search_kwargs(self.specific_query_string)
self.assertIsNone(kwargs['query'].get('query_string')) self.assertIsNone(kwargs['query'].get('query_string'))
self.assertDictEqual(kwargs['query']['filtered'].get('query'), self.default_function_score) self.assertDictEqual(kwargs['query']['filtered'].get('query'), self._default_function_score())
def test_build_search_kwargs_all_qs_no_filter(self): def test_build_search_kwargs_all_qs_no_filter(self):
with patch.object(BaseSearchBackend, 'build_models_list', return_value=[]): with patch.object(BaseSearchBackend, 'build_models_list', return_value=[]):
...@@ -73,7 +67,7 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin): ...@@ -73,7 +67,7 @@ class SimpleQuerySearchBackendMixinTestMixin(SearchBackendTestMixin):
kwargs = self.backend.build_search_kwargs(self.specific_query_string) kwargs = self.backend.build_search_kwargs(self.specific_query_string)
self.assertIsNone(kwargs['query'].get('filtered')) self.assertIsNone(kwargs['query'].get('filtered'))
self.assertDictEqual(kwargs['query'], self.default_function_score) self.assertDictEqual(kwargs['query'], self._default_function_score())
def test_build_search_kwargs_function_score(self): def test_build_search_kwargs_function_score(self):
function_score = { function_score = {
......
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