diff --git a/src/app/api/collections/descendants.py b/src/app/api/collections/descendants.py index 5d3724d..ee9420a 100644 --- a/src/app/api/collections/descendants.py +++ b/src/app/api/collections/descendants.py @@ -14,20 +14,12 @@ from app.core.models import LearningMaterialAttribute from app.elastic.dsl import qbool, qmatch from app.elastic.elastic import ResourceType, query_materials, type_filter -from app.elastic.fields import ElasticField, ElasticFieldType +from app.elastic.fields import ElasticField from app.elastic.search import Search from app.elastic.utils import handle_text_field +from app.models import CollectionAttribute as _CollectionAttribute from app.models import ElasticResourceAttribute - -class _CollectionAttribute(ElasticField): - TITLE = ("properties.cm:title", ElasticFieldType.TEXT) - DESCRIPTION = ("properties.cm:description", ElasticFieldType.TEXT) - PATH = ("path", ElasticFieldType.KEYWORD) - PARENT_ID = ("parentRef.id", ElasticFieldType.KEYWORD) - NODE_ID = ("nodeRef.id", ElasticFieldType.KEYWORD) - - _COLLECTION = TypeVar("_COLLECTION") # TODO Remove duplicate CollectionAttribute = ElasticField( diff --git a/src/app/api/collections/missing_attributes.py b/src/app/api/collections/missing_attributes.py index 036ef57..d23003a 100644 --- a/src/app/api/collections/missing_attributes.py +++ b/src/app/api/collections/missing_attributes.py @@ -9,6 +9,7 @@ from app.api.collections.models import MissingMaterials from app.api.collections.utils import all_source_fields, map_elastic_response_to_model from app.core.config import ELASTIC_TOTAL_SIZE +from app.core.models import LearningMaterialAttribute from app.elastic.dsl import qbool, qmatch from app.elastic.elastic import ResourceType, type_filter from app.elastic.search import Search @@ -19,6 +20,7 @@ ElasticResourceAttribute.NAME, ElasticResourceAttribute.KEYWORDS, CollectionAttribute.DESCRIPTION, + LearningMaterialAttribute.LICENSES, ] diff --git a/src/app/api/collections/missing_materials.py b/src/app/api/collections/missing_materials.py index fb243a1..42d9249 100644 --- a/src/app/api/collections/missing_materials.py +++ b/src/app/api/collections/missing_materials.py @@ -205,21 +205,31 @@ def materials_filter_params( def missing_attributes_search( node_id: uuid.UUID, missing_attribute: str, max_hits: int ) -> Search: + missing_attribute_filter = {"filter": type_filter[ResourceType.MATERIAL]} + if missing_attribute == LearningMaterialAttribute.LICENSES.path: - missing_attribute_query = {"filter": query_missing_material_license()} + license_query = query_missing_material_license().to_dict()["bool"] + missing_attribute_filter.update(**license_query) + + query = { + "minimum_should_match": 1, + "should": [ + qmatch(**{"path": node_id}), + qmatch(**{"nodeRef.id": node_id}), + query_missing_material_license(), + ], + **license_query, + } else: - missing_attribute_query = { - "must_not": Q("wildcard", **{missing_attribute: {"value": "*"}}) + query = { + "minimum_should_match": 1, + "should": [ + qmatch(**{"collections.path": node_id}), + qmatch(**{"collections.nodeRef.id": node_id}), + ], + "must_not": Q("wildcard", **{missing_attribute: {"value": "*"}}), + **missing_attribute_filter, } - query = { - "filter": [*type_filter[ResourceType.MATERIAL]], - "minimum_should_match": 1, - "should": [ - qmatch(**{"path": node_id}), - qmatch(**{"nodeRef.id": node_id}), - ], - **missing_attribute_query, - } return ( Search() diff --git a/tests/unit_tests/crud/test_missing_materials.py b/tests/unit_tests/crud/test_missing_materials.py index 0f35b77..9718986 100644 --- a/tests/unit_tests/crud/test_missing_materials.py +++ b/tests/unit_tests/crud/test_missing_materials.py @@ -1,29 +1,19 @@ -""" - import uuid -import pytest +from app.api.collections.missing_attributes import missing_attribute_filter +from app.api.collections.missing_materials import missing_attributes_search -from app.api.collections.missing_materials import ( - LearningMaterialAttribute, - MissingAttributeFilter, - MissingMaterialField, -) -# TODO: More tests cases to also enable filtering, see __call__ MissingAttributeFilter -@pytest.mark.skip(reason="Outdated") def test_missing_materials_search(): dummy_uuid = uuid.uuid4() - attribute = LearningMaterialAttribute.KEYWORDS - dummy_missing_attribute = MissingAttributeFilter( - attr=MissingMaterialField[attribute.name] - ) + dummy_attribute = "properties.cm:title" + dummy_missing_attribute = missing_attribute_filter[0].value dummy_maximum_size = 3 - search = missing_materials_search( + search = missing_attributes_search( dummy_uuid, dummy_missing_attribute, dummy_maximum_size ) actual = search.to_dict() - actual_source = actual["_source"] + actual_source = actual["_source"]["includes"] actual["_source"] = [] assert actual == { "query": { @@ -39,9 +29,7 @@ def test_missing_materials_search(): {"match": {"collections.nodeRef.id": dummy_uuid}}, ], "minimum_should_match": 1, - "must_not": [ - {"wildcard": {dummy_missing_attribute.attr.value: {"value": "*"}}} - ], + "must_not": [{"wildcard": {dummy_attribute: {"value": "*"}}}], } }, "from": 0, @@ -66,4 +54,35 @@ def test_missing_materials_search(): source_contains_equal_elements = actual_source == expected_source assert source_contains_equal_elements -""" + +def test_missing_materials_search_license(): + dummy_uuid = uuid.uuid4() + dummy_attribute = "properties.commonlicense_key" + dummy_missing_attribute = missing_attribute_filter[4].value + dummy_maximum_size = 3 + search = missing_attributes_search( + dummy_uuid, dummy_missing_attribute, dummy_maximum_size + ) + actual = search.to_dict() + actual["_source"] = [] + assert actual == { + "query": { + "bool": { + "filter": [ + {"term": {"permissions.Read.keyword": "GROUP_EVERYONE"}}, + {"term": {"properties.cm:edu_metadataset.keyword": "mds_oeh"}}, + {"term": {"nodeRef.storeRef.protocol": "workspace"}}, + {"term": {"type": "ccm:io"}}, + ], + "should": [ + {"match": {"collections.path": dummy_uuid}}, + {"match": {"collections.nodeRef.id": dummy_uuid}}, + ], + "minimum_should_match": 1, + "must_not": [{"wildcard": {dummy_attribute: {"value": "*"}}}], + } + }, + "from": 0, + "size": dummy_maximum_size, + "_source": [], + }