diff --git a/backend/api/projects/resources.py b/backend/api/projects/resources.py index ffbc168d7a..7cab8165c3 100644 --- a/backend/api/projects/resources.py +++ b/backend/api/projects/resources.py @@ -520,6 +520,9 @@ def setup_search_dto(self): search_dto.mapping_types = map( str, mapping_types_str.split(",") ) # Extract list from string + search_dto.mapping_types_exact = strtobool( + request.args.get("mappingTypesExact", "false") + ) project_statuses_str = request.args.get("projectStatuses") if project_statuses_str: search_dto.project_statuses = map(str, project_statuses_str.split(",")) @@ -569,6 +572,11 @@ def get(self): - in: query name: mappingTypes type: string + - in: query + name: mappingTypesExact + type: boolean + default: false + description: if true, limits projects to match the exact mapping types requested - in: query name: organisationName description: Organisation name to search for diff --git a/backend/models/dtos/project_dto.py b/backend/models/dtos/project_dto.py index 2445a8157e..51ba001f73 100644 --- a/backend/models/dtos/project_dto.py +++ b/backend/models/dtos/project_dto.py @@ -291,6 +291,7 @@ class ProjectSearchDTO(Model): preferred_locale = StringType(default="en") mapper_level = StringType(validators=[is_known_mapping_level]) mapping_types = ListType(StringType, validators=[is_known_mapping_type]) + mapping_types_exact = BooleanType(required=False) project_statuses = ListType(StringType, validators=[is_known_project_status]) organisation_name = StringType() organisation_id = IntType() diff --git a/backend/services/project_search_service.py b/backend/services/project_search_service.py index 6c0fe23704..897c98c0bc 100644 --- a/backend/services/project_search_service.py +++ b/backend/services/project_search_service.py @@ -263,12 +263,21 @@ def _filter_projects(search_dto: ProjectSearchDTO, user): if search_dto.mapping_types: # Construct array of mapping types for query mapping_type_array = [] - mapping_type_array = [ - MappingTypes[mapping_type].value - for mapping_type in search_dto.mapping_types - ] - query = query.filter(Project.mapping_types.contains(mapping_type_array)) + if search_dto.mapping_types_exact: + mapping_type_array = [ + { + MappingTypes[mapping_type].value + for mapping_type in search_dto.mapping_types + } + ] + query = query.filter(Project.mapping_types.in_(mapping_type_array)) + else: + mapping_type_array = [ + MappingTypes[mapping_type].value + for mapping_type in search_dto.mapping_types + ] + query = query.filter(Project.mapping_types.overlap(mapping_type_array)) if search_dto.text_search: # We construct an OR search, so any projects that contain or more of the search terms should be returned