Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add is_incomplete_or_stale to the search index #1627

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions learning_resources/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class LearningResourceFactory(DjangoModelFactory):
departments = factory.PostGeneration(_post_gen_departments)
topics = factory.PostGeneration(_post_gen_topics)
content_tags = factory.PostGeneration(_post_gen_tags)
completeness = 1
published = True
delivery = factory.List(random.choices(LearningResourceDelivery.names())) # noqa: S311
professional = factory.LazyAttribute(
Expand Down
4 changes: 4 additions & 0 deletions learning_resources_search/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,7 @@ def test_execute_learn_search_for_learning_resource_query(opensearch):
"is_learning_material",
"resource_age_date",
"featured_rank",
"is_incomplete_or_stale",
]
},
}
Expand Down Expand Up @@ -1921,6 +1922,7 @@ def test_execute_learn_search_with_script_score(
"is_learning_material",
"resource_age_date",
"featured_rank",
"is_incomplete_or_stale",
]
},
}
Expand Down Expand Up @@ -2349,6 +2351,7 @@ def test_execute_learn_search_with_min_score(mocker, settings, opensearch):
"is_learning_material",
"resource_age_date",
"featured_rank",
"is_incomplete_or_stale",
]
},
}
Expand Down Expand Up @@ -2559,6 +2562,7 @@ def test_execute_learn_search_for_content_file_query(opensearch):
"is_learning_material",
"resource_age_date",
"featured_rank",
"is_incomplete_or_stale",
]
},
}
Expand Down
2 changes: 2 additions & 0 deletions learning_resources_search/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class FilterConfig:
},
"free": {"type": "boolean"},
"is_learning_material": {"type": "boolean"},
"is_incomplete_or_stale": {"type": "boolean"},
"delivery": {
"type": "nested",
"properties": {
Expand Down Expand Up @@ -416,6 +417,7 @@ class FilterConfig:
"is_learning_material",
"resource_age_date",
"featured_rank",
"is_incomplete_or_stale",
]

LEARNING_RESOURCE_SEARCH_SORTBY_OPTIONS = {
Expand Down
16 changes: 13 additions & 3 deletions learning_resources_search/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ def serialize_learning_resource_for_update(
dict: The serialized and transformed resource data

"""
STALENESS_CUTOFF = 2010
COMPLETENESS_CUTOFF = 0.5

serialized_data = LearningResourceSerializer(instance=learning_resource_obj).data

if learning_resource_obj.resource_type == LearningResourceType.course.name:
Expand All @@ -146,15 +149,22 @@ def serialize_learning_resource_for_update(
else:
featured_rank = None

resource_age_date = get_resource_age_date(
learning_resource_obj, serialized_data["resource_category"]
)

is_incomplete_or_stale = (
resource_age_date and resource_age_date.year <= STALENESS_CUTOFF
) or (learning_resource_obj.completeness < COMPLETENESS_CUTOFF)

return {
"resource_relations": {"name": "resource"},
"created_on": learning_resource_obj.created_on,
"is_learning_material": serialized_data["resource_category"]
== LEARNING_MATERIAL_RESOURCE_CATEGORY,
"resource_age_date": get_resource_age_date(
learning_resource_obj, serialized_data["resource_category"]
),
"resource_age_date": resource_age_date,
"featured_rank": featured_rank,
"is_incomplete_or_stale": is_incomplete_or_stale,
**serialized_data,
}

Expand Down
38 changes: 29 additions & 9 deletions learning_resources_search/serializers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ def test_serialize_bulk_learning_resources(mocker):
"resource_age_date": mocker.ANY,
"is_learning_material": mocker.ANY,
"featured_rank": None,
"is_incomplete_or_stale": mocker.ANY,
**LearningResourceSerializer(instance=resource).data,
}

Expand All @@ -637,30 +638,47 @@ def test_serialize_bulk_learning_resources(mocker):
@pytest.mark.parametrize("is_professional", [True, False])
@pytest.mark.parametrize("no_price", [True, False])
@pytest.mark.parametrize("has_featured_rank", [True, False])
def test_serialize_learning_resource_for_bulk(
mocker, resource_type, is_professional, no_price, has_featured_rank
@pytest.mark.parametrize("is_stale", [True, False])
@pytest.mark.parametrize("is_incomplete", [True, False])
def test_serialize_learning_resource_for_bulk( # noqa: PLR0913
mocker,
resource_type,
is_professional,
no_price,
has_featured_rank,
is_stale,
is_incomplete,
):
"""
Test that serialize_program_for_bulk yields a valid LearningResourceSerializer for resource types other than "course"
The "course" resource type is tested by `test_serialize_course_numbers_for_bulk` below.
"""
completeness = 0.24 if is_incomplete else 0.75
resource = factories.LearningResourceFactory.create(
resource_type=resource_type, professional=is_professional, runs=[]
resource_type=resource_type,
professional=is_professional,
runs=[],
completeness=completeness,
)

LearningResourceRunFactory.create(
learning_resource=resource, prices=[Decimal(0.00 if no_price else 1.00)]
)

resource_age_date = datetime(
2009 if is_stale else 2024, 1, 1, 1, 1, 1, 0, tzinfo=UTC
)

mocker.patch(
"learning_resources_search.serializers.get_resource_age_date",
return_value=resource_age_date,
)
free_dict = {
"free": resource_type
not in [LearningResourceType.program.name, LearningResourceType.course.name]
or (no_price and not is_professional)
}

mocker.patch(
"learning_resources_search.serializers.get_resource_age_date",
return_value=datetime(2024, 1, 1, 1, 1, 1, 0, tzinfo=UTC),
)

if has_featured_rank:
mocker.patch(
"learning_resources_search.serializers.random",
Expand Down Expand Up @@ -692,8 +710,9 @@ def test_serialize_learning_resource_for_bulk(
"resource_relations": {"name": "resource"},
"created_on": resource.created_on,
"is_learning_material": resource.resource_type not in ["course", "program"],
"resource_age_date": datetime(2024, 1, 1, 1, 1, 1, 0, tzinfo=UTC),
"resource_age_date": resource_age_date,
"featured_rank": 3.4 if has_featured_rank else None,
"is_incomplete_or_stale": is_incomplete or is_stale,
**free_dict,
**LearningResourceSerializer(resource).data,
}
Expand Down Expand Up @@ -818,6 +837,7 @@ def test_serialize_course_numbers_for_bulk(
"is_learning_material": False,
"resource_age_date": datetime(2024, 1, 1, 1, 1, 1, 0, tzinfo=UTC),
"featured_rank": None,
"is_incomplete_or_stale": False,
**LearningResourceSerializer(resource).data,
}
expected_data["course"]["course_numbers"][0] = {
Expand Down
Loading