From 32ebbf528cf32f59ca17672db65e65ff8099af98 Mon Sep 17 00:00:00 2001 From: Cristina <579522+CristinaRO@users.noreply.github.com> Date: Thu, 21 Mar 2024 16:42:41 +0000 Subject: [PATCH] Extract facets from search results Co-authored-by: adam-murray Signed-off-by: Cristina <579522+CristinaRO@users.noreply.github.com> --- CHANGELOG.md | 4 ++- .../responses/search_response.py | 17 +++++++++++ tests/conftest.py | 15 +++++++++- tests/responses/test_search_response.py | 29 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f45e559..4b01c520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog 1.0.0]. ## Unreleased + - Remove fcl_ex_id_ prefix from UUID of reparse execution ID +- Implement handling of facets received from MarkLogic search results ## [Release 22.1.0] @@ -13,7 +15,7 @@ The format is based on [Keep a Changelog 1.0.0]. - Add a `validates_against_schema` property - Add a `can_enrich` property - Only enrich if not recently enriched and valid against current schema -- Allow fetching linked docuements for `Judgement`s and `PressSummary`s +- Allow fetching linked documents for `Judgement`s and `PressSummary`s - Add function to check if the docx exists for a judgment ## [Release 22.0.2] diff --git a/src/caselawclient/responses/search_response.py b/src/caselawclient/responses/search_response.py index f5cf034c..804a387f 100644 --- a/src/caselawclient/responses/search_response.py +++ b/src/caselawclient/responses/search_response.py @@ -45,3 +45,20 @@ def results(self) -> List[SearchResult]: "//search:response/search:result", namespaces=self.NAMESPACES ) return [SearchResult(result, self.client) for result in results] + + @property + def facets(self) -> dict[str, str]: + """ + Returns search facets from the SearchResponse as a dictionary + + :return: A flattened dictionary of search facet values + """ + # TODO: preserve the name of the facet (e.g. "court", "year") + results = self.node.xpath( + "//search:response/search:facet/search:facet-value", + namespaces={"search": "http://marklogic.com/appservices/search"}, + ) + facets_dictionary = { + result.attrib["name"]: result.attrib["count"] for result in results + } + return facets_dictionary diff --git a/tests/conftest.py b/tests/conftest.py index a5f4174d..344f8422 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,6 +34,18 @@ def valid_search_result_xml_fixture() -> str: ) +@pytest.fixture(name="valid_facets_fixture_xml") +def valid_facets_xml_fixture() -> str: + return ( + '' + '' + ' UKUT-AAC' + 'EAT' + 'EWCA-Civil' + "" + ) + + @pytest.fixture(name="generate_search_response_xml") def generate_search_response_xml_fixture() -> Callable: """ @@ -43,7 +55,7 @@ def generate_search_response_xml_fixture() -> Callable: Callable: Function that generates search response XML. """ - def _generate_search_response_xml(response_content: str) -> str: + def _generate_search_response_xml(response_content: str, facets="") -> str: """ Generate a search response XML string. @@ -56,6 +68,7 @@ def _generate_search_response_xml(response_content: str) -> str: return ( '' # noqa: E501 f"{response_content}" + f"{facets}" "" ) diff --git a/tests/responses/test_search_response.py b/tests/responses/test_search_response.py index c99a2369..a73b76fe 100644 --- a/tests/responses/test_search_response.py +++ b/tests/responses/test_search_response.py @@ -79,3 +79,32 @@ def test_when_search_namespace_prefix_not_defined_on_response_xml_syntax_error_r match="Namespace prefix search on response is not defined", ): SearchResponse(etree.fromstring(xml_without_namespace), self.client) + + def test_facets( + self, + valid_search_result_xml, + valid_facets_fixture_xml, + generate_search_response_xml, + ): + """ + Given a SearchResponse instance with n facets + When calling 'facets' on it + Then it should return a list of n elements + And each element's node attribute should be as expected + """ + search_response = SearchResponse( + etree.fromstring( + generate_search_response_xml( + valid_search_result_xml, valid_facets_fixture_xml + ) + ), + self.client, + ) + + results = search_response.facets + + assert len(results) == 4 + assert results[""] == "14" + assert results[" UKUT-AAC"] == "1" + assert results["EAT"] == "649" + assert results["EWCA-Civil"] == "5768"