def test_hybrid_search_structured_opposite_retrieval_and_ranking(self):
        """
        Tests that hybrid search with:
        retrievalMethod = "lexical", rankingMethod = "tensor" and
        retrievalMethod = "tensor", rankingMethod = "lexical"

        have expected results. The documents themselves should exactly match retrieval method, but the scores
        should match the ranking method. This is only consistent for single-field search, as retrieval top k will
        match the ranking top k.

        Uses structured index, so we have searchable attributes.
        """

        # Add documents
        self.add_documents(
            config=self.config,
            add_docs_params=AddDocsParams(
                index_name=self.structured_text_index_score_modifiers.name,
                docs=self.docs_list
            )
        )

        # Reference results
        tensor_res_all_docs = tensor_search.search(  # To get tensor scores of every doc, for reference
            config=self.config,
            index_name=self.structured_text_index_score_modifiers.name,
            text="dogs",
            search_method="TENSOR",
            searchable_attributes=["text_field_1"],
            result_count=20,
        )
        lexical_res = tensor_search.search(
            config=self.config,
            index_name=self.structured_text_index_score_modifiers.name,
            text="dogs",
            search_method="LEXICAL",
            searchable_attributes=["text_field_1"],
            result_count=10,
        )
        tensor_res = tensor_search.search(
            config=self.config,
            index_name=self.structured_text_index_score_modifiers.name,
            text="dogs",
            search_method="TENSOR",
            result_count=10,
            searchable_attributes=["text_field_1"]
        )

        # Lexical retrieval with Tensor ranking
        with self.subTest(retrievalMethod=RetrievalMethod.Lexical, rankingMethod=RankingMethod.Tensor):
            hybrid_res = tensor_search.search(
                config=self.config,
                index_name=self.structured_text_index_score_modifiers.name,
                text="dogs",
                search_method="HYBRID",
                hybrid_parameters=HybridParameters(
                    retrievalMethod=RetrievalMethod.Lexical,
                    rankingMethod=RankingMethod.Tensor,
                    searchableAttributesLexical=["text_field_1"],
                    searchableAttributesTensor=["text_field_1"],
                    verbose=True
                ),
                result_count=10
            )
            self.assertIn("hits", hybrid_res)

            # RETRIEVAL: 10 documents must match the 10 from lexical search (order may differ)
            self.assertEqual(len(hybrid_res["hits"]), len(lexical_res["hits"]))
            lexical_res_ids = [doc["_id"] for doc in lexical_res["hits"]]
            for hybrid_hit in hybrid_res["hits"]:
                self.assertIn(hybrid_hit["_id"], lexical_res_ids)

            # RANKING: scores must match the tensor search scores
            for hybrid_hit in hybrid_res["hits"]:
                tensor_hit = next(doc for doc in tensor_res_all_docs["hits"] if doc["_id"] == hybrid_hit["_id"])
                self.assertEqual(hybrid_hit["_score"], tensor_hit["_score"])

        # Tensor retrieval with Lexical ranking
        with self.subTest(retrievalMethod=RetrievalMethod.Tensor, rankingMethod=RankingMethod.Lexical):
            hybrid_res = tensor_search.search(
                config=self.config,
                index_name=self.structured_text_index_score_modifiers.name,
                text="dogs",
                search_method="HYBRID",
                hybrid_parameters=HybridParameters(
                    retrievalMethod=RetrievalMethod.Tensor,
                    rankingMethod=RankingMethod.Lexical,
                    searchableAttributesLexical=["text_field_1"],
                    searchableAttributesTensor=["text_field_1"],
                    verbose=True
                ),
                result_count=10
            )

            self.assertIn("hits", hybrid_res)

            # RETRIEVAL: 10 documents must match the 10 from tensor search (order may differ)
            self.assertEqual(len(hybrid_res["hits"]), len(tensor_res["hits"]))
            tensor_res_ids = [doc["_id"] for doc in tensor_res["hits"]]
            for hybrid_hit in hybrid_res["hits"]:
                self.assertIn(hybrid_hit["_id"], tensor_res_ids)

            # RANKING: scores must match the lexical search scores
            for hybrid_hit in hybrid_res["hits"]:
                if hybrid_hit["_score"] > 0:
                    # Score should match its counterpart in lexical search
                    lexical_hit = next(doc for doc in lexical_res["hits"] if doc["_id"] == hybrid_hit["_id"])
                    self.assertEqual(hybrid_hit["_score"], lexical_hit["_score"])
                else:
                    # If score is 0, it should not be in lexical search results
                    self.assertNotIn(hybrid_hit["_id"], [doc["_id"] for doc in lexical_res["hits"]])

        Tests that hybrid search with:
        retrievalMethod = "lexical", rankingMethod = "tensor" and
        retrievalMethod = "tensor", rankingMethod = "lexical"

        have expected results. The documents themselves should exactly match retrieval method, but the scores
        should match the ranking method. This is only consistent for single-field search, as retrieval top k will
        match the ranking top k.

        Uses structured index, so we have searchable attributes.
        
tests/integ_tests/tensor_search/integ_tests/test_hybrid_search.py