Commit a604def4 by Anthony Mangano

Add boosting config for enrollable CourseRuns

ECOM-7038
parent 72c3be00
...@@ -598,6 +598,8 @@ class SearchBoostingTests(ElasticsearchTestMixin, TestCase): ...@@ -598,6 +598,8 @@ class SearchBoostingTests(ElasticsearchTestMixin, TestCase):
defaults = { defaults = {
'pacing_type': 'instructor_paced', 'pacing_type': 'instructor_paced',
'start': datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(weeks=52), 'start': datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(weeks=52),
'enrollment_start': datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(weeks=50),
'enrollment_end': None
} }
defaults.update(kwargs) defaults.update(kwargs)
return CourseRunFactory(**defaults) return CourseRunFactory(**defaults)
...@@ -667,3 +669,45 @@ class SearchBoostingTests(ElasticsearchTestMixin, TestCase): ...@@ -667,3 +669,45 @@ class SearchBoostingTests(ElasticsearchTestMixin, TestCase):
self.assertEqual(2, len(search_results)) self.assertEqual(2, len(search_results))
self.assertGreater(search_results[0].score, search_results[1].score) self.assertGreater(search_results[0].score, search_results[1].score)
self.assertEqual(str(test_record.type), str(search_results[0].type)) self.assertEqual(str(test_record.type), str(search_results[0].type))
@ddt.data(
# Case 1: Should get boost if enrollment_start and enrollment_end unspecified.
(None, None, True),
# Case 2: Should get boost if enrollment_start unspecified and enrollment_end in future.
(None, datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(days=15), True),
# Case 3: Should get boost if enrollment_start in past and enrollment_end unspecified.
(datetime.datetime.now(pytz.timezone('utc')) - datetime.timedelta(days=15), None, True),
# Case 4: Should get boost if enrollment_start in past and enrollment_end in future.
(datetime.datetime.now(pytz.timezone('utc')) - datetime.timedelta(days=15),
datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(days=15),
True),
# Case 5: Should not get boost if enrollment_start in future.
(datetime.datetime.now(pytz.timezone('utc')) + datetime.timedelta(days=15), None, False),
# Case 5: Should not get boost if enrollment_end in past.
(None, datetime.datetime.now(pytz.timezone('utc')) - datetime.timedelta(days=15), False),
)
@ddt.unpack
def test_enrollable_course_run_boosting(self, enrollment_start, enrollment_end, expects_boost):
""" Verify that enrollable CourseRuns are boosted."""
# Create a control record that should never be boosted
self.build_normalized_course_run(title='test1')
# Create the test record
test_record = self.build_normalized_course_run(
title='test2',
enrollment_start=enrollment_start,
enrollment_end=enrollment_end
)
search_results = SearchQuerySet().models(CourseRun).all()
self.assertEqual(2, len(search_results))
if expects_boost:
self.assertGreater(search_results[0].score, search_results[1].score)
self.assertEqual(test_record.title, search_results[0].title)
else:
self.assertEqual(search_results[0].score, search_results[1].score)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2017-02-01 20:43
from __future__ import unicode_literals
from django.db import migrations
def add_enrollable_course_run_boosting(apps, schema_editor):
"""Add enrollable CourseRun boosting function to ElasticsearchBoostConfig instance."""
# 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,
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': 'Professional Certificate'}}, 'weight': 1.0},
{'filter': {'term': {'type_exact': 'MicroMasters'}}, 'weight': 1.0},
{'linear': {'start': {'origin': 'now', 'decay': 0.95, 'scale': '1d'}}, 'weight': 5.0},
# Boost function for CourseRuns with enrollable paid Seats.
# We want to boost if:
# - The course run has at least one enrollable paid Seat (has_enrollable_paid_seats is True)
# AND one of the following two conditions are true
# - The paid_seat_enrollment_end is unspecified.
# - The paid_seat_enrollment_end is in the future.
# We apply a weight of 1.0 to match the boost given for self paced courses.
{
'filter': {
'bool': {
'must': [
{'exists': {'field': 'has_enrollable_paid_seats'}},
{'term': {'has_enrollable_paid_seats': True}}
],
'should': [
{'bool': {'must_not': { 'exists': {'field': 'paid_seat_enrollment_end'}}}},
{'range': {'paid_seat_enrollment_end': {'gte': 'now'}}}
]
}
},
'weight': 1.0
},
# Boost function for enrollable CourseRuns.
# We want to boost if:
# - enrollment_start and enrollment_end are unspecified
# - enrollment_start is unspecified and enrollment_end is in the future
# - enrollment_end is unspecified and enrollment_start is in the past
# - enrollment_start is in the past and enrollment_end is in the future
# We apply a weight of 1.0 to match the boost given for self paced and enrollable paid courses.
{
'filter': {
'bool': {
'should': [
{'bool': {
'must_not': [
{'exists': {'field': 'enrollment_start'}},
{'exists': {'field': 'enrollment_end'}}
]
}},
{'bool': {
'must_not': {'exists': {'field': 'enrollment_start'}},
'must': [
{'exists': {'field': 'enrollment_end'}},
{'range': {'enrollment_end': {'gt': 'now'}}}
]
}},
{'bool': {
'must_not': {'exists': {'field': 'enrollment_end'}},
'must': [
{'exists': {'field': 'enrollment_start'}},
{'range': {'enrollment_start': {'lte': 'now'}}}
]
}},
{'bool': {
'must': [
{'exists': {'field': 'enrollment_start'}},
{'exists': {'field': 'enrollment_end'}},
{'range': {'enrollment_start': {'lte': 'now'}}},
{'range': {'enrollment_end': {'gt': 'now'}}}
]
}}
]
}
},
'weight': 1.0
}
]
}
}
)
class Migration(migrations.Migration):
dependencies = [
('edx_haystack_extensions', '0004_auto_20170126_1510'),
]
operations = [
migrations.RunPython(add_enrollable_course_run_boosting, migrations.RunPython.noop)
]
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