From 011345f27351ee29ef760a452ecf4acc7d604716 Mon Sep 17 00:00:00 2001 From: simorenoh Date: Mon, 14 Oct 2024 17:10:48 -0700 Subject: [PATCH 1/6] FTS control plane changes --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 1 + sdk/cosmos/azure-cosmos/README.md | 46 ++++++++++++++ .../azure/cosmos/aio/_database.py | 16 +++++ .../azure-cosmos/azure/cosmos/database.py | 16 +++++ .../azure-cosmos/samples/index_management.py | 60 ++++++++++++++++++- .../samples/index_management_async.py | 58 ++++++++++++++++++ .../test/test_full_text_policy.py | 51 ++++++++++++++++ .../test/test_full_text_policy_async.py | 60 +++++++++++++++++++ 8 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 sdk/cosmos/azure-cosmos/test/test_full_text_policy.py create mode 100644 sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index df20a43c36bf..0ad17adc49c4 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -3,6 +3,7 @@ ### 4.7.1 (Unreleased) #### Features Added +* Added full text policy and full text indexing policy. See [](). * Added Retry Policy for Container Recreate in the Python SDK. See [PR 36043](https://github.com/Azure/azure-sdk-for-python/pull/36043) * Added option to disable write payload on writes. See [PR 37365](https://github.com/Azure/azure-sdk-for-python/pull/37365) * Added get feed ranges API. See [PR 37687](https://github.com/Azure/azure-sdk-for-python/pull/37687) diff --git a/sdk/cosmos/azure-cosmos/README.md b/sdk/cosmos/azure-cosmos/README.md index cedf4c5b3c7a..dc3f71462afc 100644 --- a/sdk/cosmos/azure-cosmos/README.md +++ b/sdk/cosmos/azure-cosmos/README.md @@ -728,6 +728,52 @@ not being able to recognize the new NonStreamingOrderBy capability that makes ve If this happens, you can set the `AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY` environment variable to `"True"` to opt out of this functionality and continue operating as usual.* +### TBD - Full Text Policy and Full Text Indexes +We have added new capabilities to utilize full text policies and full text indexing for users to leverage full text search +utilizing our Cosmos SDK. These two container-level configurations have to be turned on at the account-level +before you can use them. + +A full text policy allows the user to define the default language to be used for all full text paths, or to set +a language for each path individually in case the user would like to use full text search on data containing different +languages in different fields. + +A sample full text policy would look like this: +```python +full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/text1", + "language": "en-US" + }, + { + "path": "/text2", + "language": "en-US" + } + ] +} +``` +For all supported languages, see [here](). + +Full text search indexes have been added to the already existing indexing_policy and only require the path to the +relevant field to be used. +A sample indexing policy with full text search indexes would look like this: +```python +indexing_policy = { + "automatic": True, + "indexingMode": "consistent", + "compositeIndexes": [ + [ + {"path": "/numberField", "order": "ascending"}, + {"path": "/stringField", "order": "descending"} + ] + ], + "fullTextIndexes": [ + {"path": "/abstract"} + ] + } +``` + ## Troubleshooting ### General diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_database.py b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_database.py index 513384d55311..21b77de57ed8 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_database.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_database.py @@ -173,6 +173,7 @@ async def create_container( match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, vector_embedding_policy: Optional[Dict[str, Any]] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Create a new container with the given ID (name). @@ -206,6 +207,9 @@ async def create_container( :keyword Dict[str, Any] vector_embedding_policy: The vector embedding policy for the container. Each vector embedding possesses a predetermined number of dimensions, is associated with an underlying data type, and is generated for a particular distance function. + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container creation failed. :returns: A `ContainerProxy` instance representing the new container. :rtype: ~azure.cosmos.aio.ContainerProxy @@ -251,6 +255,8 @@ async def create_container( definition["computedProperties"] = computed_properties if vector_embedding_policy is not None: definition["vectorEmbeddingPolicy"] = vector_embedding_policy + if full_text_policy is not None: + definition["fullTextPolicy"] = full_text_policy if session_token is not None: kwargs['session_token'] = session_token @@ -285,6 +291,7 @@ async def create_container_if_not_exists( match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, vector_embedding_policy: Optional[Dict[str, Any]] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Create a container if it does not exist already. @@ -320,6 +327,9 @@ async def create_container_if_not_exists( :keyword Dict[str, Any] vector_embedding_policy: **provisional** The vector embedding policy for the container. Each vector embedding possesses a predetermined number of dimensions, is associated with an underlying data type, and is generated for a particular distance function. + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container creation failed. :returns: A `ContainerProxy` instance representing the new container. :rtype: ~azure.cosmos.aio.ContainerProxy @@ -349,6 +359,7 @@ async def create_container_if_not_exists( session_token=session_token, initial_headers=initial_headers, vector_embedding_policy=vector_embedding_policy, + full_text_policy=full_text_policy, **kwargs ) @@ -482,6 +493,7 @@ async def replace_container( etag: Optional[str] = None, match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Reset the properties of the container. @@ -509,6 +521,9 @@ async def replace_container( note that analytical storage can only be enabled on Synapse Link enabled accounts. :keyword response_hook: A callable invoked with the response metadata. :paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None] + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :returns: A `ContainerProxy` instance representing the container after replace completed. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: Raised if the container couldn't be replaced. This includes if the container with given id does not exist. @@ -545,6 +560,7 @@ async def replace_container( "defaultTtl": default_ttl, "conflictResolutionPolicy": conflict_resolution_policy, "analyticalStorageTtl": analytical_storage_ttl, + "fullTextPolicy": full_text_policy }.items() if value is not None } diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/database.py b/sdk/cosmos/azure-cosmos/azure/cosmos/database.py index 8653b38860da..6b4d58e31c2b 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/database.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/database.py @@ -174,6 +174,7 @@ def create_container( # pylint:disable=docstring-missing-param match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, vector_embedding_policy: Optional[Dict[str, Any]] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Create a new container with the given ID (name). @@ -203,6 +204,9 @@ def create_container( # pylint:disable=docstring-missing-param :keyword Dict[str, Any] vector_embedding_policy: **provisional** The vector embedding policy for the container. Each vector embedding possesses a predetermined number of dimensions, is associated with an underlying data type, and is generated for a particular distance function. + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :returns: A `ContainerProxy` instance representing the new container. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container creation failed. :rtype: ~azure.cosmos.ContainerProxy @@ -246,6 +250,8 @@ def create_container( # pylint:disable=docstring-missing-param definition["computedProperties"] = computed_properties if vector_embedding_policy is not None: definition["vectorEmbeddingPolicy"] = vector_embedding_policy + if full_text_policy is not None: + definition["fullTextPolicy"] = full_text_policy if session_token is not None: kwargs['session_token'] = session_token @@ -287,6 +293,7 @@ def create_container_if_not_exists( # pylint:disable=docstring-missing-param match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, vector_embedding_policy: Optional[Dict[str, Any]] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Create a container if it does not exist already. @@ -318,6 +325,9 @@ def create_container_if_not_exists( # pylint:disable=docstring-missing-param :keyword Dict[str, Any] vector_embedding_policy: The vector embedding policy for the container. Each vector embedding possesses a predetermined number of dimensions, is associated with an underlying data type, and is generated for a particular distance function. + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :returns: A `ContainerProxy` instance representing the container. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container read or creation failed. :rtype: ~azure.cosmos.ContainerProxy @@ -349,6 +359,7 @@ def create_container_if_not_exists( # pylint:disable=docstring-missing-param session_token=session_token, initial_headers=initial_headers, vector_embedding_policy=vector_embedding_policy, + full_text_policy=full_text_policy, **kwargs ) @@ -538,6 +549,7 @@ def replace_container( # pylint:disable=docstring-missing-param etag: Optional[str] = None, match_condition: Optional[MatchConditions] = None, analytical_storage_ttl: Optional[int] = None, + full_text_policy: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> ContainerProxy: """Reset the properties of the container. @@ -562,6 +574,9 @@ def replace_container( # pylint:disable=docstring-missing-param None leaves analytical storage off and a value of -1 turns analytical storage on with no TTL. Please note that analytical storage can only be enabled on Synapse Link enabled accounts. :keyword Callable response_hook: A callable invoked with the response metadata. + :keyword Dict[str, Any] full_text_policy: **provisional** The full text policy for the container. + Used to denote the default language to be used for all full text indexes, or to individually + assign a language to each full text index path. :returns: A `ContainerProxy` instance representing the container after replace completed. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: Raised if the container couldn't be replaced. This includes if the container with given id does not exist. @@ -603,6 +618,7 @@ def replace_container( # pylint:disable=docstring-missing-param "defaultTtl": default_ttl, "conflictResolutionPolicy": conflict_resolution_policy, "analyticalStorageTtl": analytical_storage_ttl, + "fullTextPolicy": full_text_policy, }.items() if value is not None } diff --git a/sdk/cosmos/azure-cosmos/samples/index_management.py b/sdk/cosmos/azure-cosmos/samples/index_management.py index bc801da1a4b6..f0556256b942 100644 --- a/sdk/cosmos/azure-cosmos/samples/index_management.py +++ b/sdk/cosmos/azure-cosmos/samples/index_management.py @@ -637,7 +637,7 @@ def use_geospatial_indexing_policy(db): try: delete_container_if_exists(db, CONTAINER_ID) - # Create a container with vector embedding policy and vector indexes + # Create a container with geospatial indexes indexing_policy = { 'includedPaths': [ {'path': '/"Location"/?', @@ -746,6 +746,61 @@ def get_embeddings(num): print("Entity doesn't exist") +def use_full_text_policy(db): + try: + delete_container_if_exists(db, CONTAINER_ID) + + # Create a container with full text policy and full text indexes + indexing_policy = { + "automatic": True, + "fullTextIndexes": [ + {"path": "/text1"} + ] + } + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/text1", + "language": "en-US" + }, + { + "path": "/text2", + "language": "en-US" + } + ] + } + + created_container = db.create_container( + id=CONTAINER_ID, + partition_key=PARTITION_KEY, + indexing_policy=indexing_policy, + full_text_policy=full_text_policy + ) + properties = created_container.read() + print(created_container) + + print("\n" + "-" * 25 + "\n11. Container created with full text policy and full text indexes") + print_dictionary_items(properties["indexingPolicy"]) + print_dictionary_items(properties["fullTextPolicy"]) + + # Create some items to use with full text search + for i in range(10): + created_container.create_item({"id": "full_text_item" + str(i), "text1": "some-text"}) + + # Run full text search queries using ranking + query = "select * from c" + query_documents_with_custom_query(created_container, query) + + # Cleanup + db.delete_container(created_container) + print("\n") + except exceptions.CosmosResourceExistsError: + print("Entity already exists") + except exceptions.CosmosResourceNotFoundError: + print("Entity doesn't exist") + + def run_sample(): try: client = obtain_client() @@ -782,6 +837,9 @@ def run_sample(): # 10. Create and use a vector embedding policy use_vector_embedding_policy(created_db) + # 11. Create and use a full text policy + use_full_text_policy(created_db) + except exceptions.AzureError as e: raise e diff --git a/sdk/cosmos/azure-cosmos/samples/index_management_async.py b/sdk/cosmos/azure-cosmos/samples/index_management_async.py index c9d5f1d8f6b3..dfeda187a583 100644 --- a/sdk/cosmos/azure-cosmos/samples/index_management_async.py +++ b/sdk/cosmos/azure-cosmos/samples/index_management_async.py @@ -741,6 +741,61 @@ def get_embeddings(num): print("Entity doesn't exist") +async def use_full_text_policy(db): + try: + await delete_container_if_exists(db, CONTAINER_ID) + + # Create a container with full text policy and full text indexes + indexing_policy = { + "automatic": True, + "fullTextIndexes": [ + {"path": "/text1"} + ] + } + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/text1", + "language": "en-US" + }, + { + "path": "/text2", + "language": "en-US" + } + ] + } + + created_container = await db.create_container( + id=CONTAINER_ID, + partition_key=PARTITION_KEY, + indexing_policy=indexing_policy, + full_text_policy=full_text_policy + ) + properties = await created_container.read() + print(created_container) + + print("\n" + "-" * 25 + "\n11. Container created with full text policy and full text indexes") + print_dictionary_items(properties["indexingPolicy"]) + print_dictionary_items(properties["fullTextPolicy"]) + + # Create some items to use with full text search + for i in range(10): + created_container.create_item({"id": "full_text_item" + str(i), "text1": "some-text"}) + + # Run full text search queries using ranking + query = "select * from c" + await query_documents_with_custom_query(created_container, query) + + # Cleanup + db.delete_container(created_container) + print("\n") + except exceptions.CosmosResourceExistsError: + print("Entity already exists") + except exceptions.CosmosResourceNotFoundError: + print("Entity doesn't exist") + + async def run_sample(): try: async with obtain_client() as client: @@ -777,6 +832,9 @@ async def run_sample(): # 10. Create and use a vector embedding policy await use_vector_embedding_policy(created_db) + # 11. Create and use a full text policy + await use_full_text_policy(created_db) + except exceptions.AzureError as e: raise e diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py new file mode 100644 index 000000000000..370f15cd3143 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py @@ -0,0 +1,51 @@ +# The MIT License (MIT) +# Copyright (c) Microsoft Corporation. All rights reserved. + +import unittest +import uuid + +import pytest + +import azure.cosmos.exceptions as exceptions +import test_config +from azure.cosmos import CosmosClient, PartitionKey + + +class TestFullTextPolicy(unittest.TestCase): + client: CosmosClient = None + host = test_config.TestConfig.host + masterKey = test_config.TestConfig.masterKey + connectionPolicy = test_config.TestConfig.connectionPolicy + + @classmethod + def setUpClass(cls): + if (cls.masterKey == '[YOUR_KEY_HERE]' or + cls.host == '[YOUR_ENDPOINT_HERE]'): + raise Exception( + "You must specify your Azure Cosmos account values for " + "'masterKey' and 'host' at the top of this class to run the " + "tests.") + + cls.client = CosmosClient(cls.host, cls.masterKey) + cls.created_database = cls.client.get_database_client(test_config.TestConfig.TEST_DATABASE_ID) + cls.test_db = cls.client.create_database(str(uuid.uuid4())) + + def test_create_full_text_container(self): + return + + def test_fail_create_full_text_policy(self): + return + + def test_fail_create_full_text_indexing_policy(self): + return + + def test_replace_full_text_policy(self): + return + + def test_replace_full_text_indexing_policy(self): + return + + + +if __name__ == '__main__': + unittest.main() diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py new file mode 100644 index 000000000000..0e9be4112c16 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py @@ -0,0 +1,60 @@ +# The MIT License (MIT) +# Copyright (c) Microsoft Corporation. All rights reserved. + +import unittest +import uuid + +import pytest + +import azure.cosmos.exceptions as exceptions +import test_config +from azure.cosmos import PartitionKey +from azure.cosmos.aio import CosmosClient, DatabaseProxy + + +class TestFullTextPolicyAsync(unittest.IsolatedAsyncioTestCase): + host = test_config.TestConfig.host + masterKey = test_config.TestConfig.masterKey + connectionPolicy = test_config.TestConfig.connectionPolicy + + client: CosmosClient = None + created_database: DatabaseProxy = None + + TEST_DATABASE_ID = test_config.TestConfig.TEST_DATABASE_ID + + @classmethod + def setUpClass(cls): + if (cls.masterKey == '[YOUR_KEY_HERE]' or + cls.host == '[YOUR_ENDPOINT_HERE]'): + raise Exception( + "You must specify your Azure Cosmos account values for " + "'masterKey' and 'host' at the top of this class to run the " + "tests.") + + async def asyncSetUp(self): + self.client = CosmosClient(self.host, self.masterKey) + self.created_database = self.client.get_database_client(self.TEST_DATABASE_ID) + self.test_db = await self.client.create_database(str(uuid.uuid4())) + + async def tearDown(self): + await self.client.delete_database(self.test_db.id) + await self.client.close() + + async def test_create_full_text_container_async(self): + return + + async def test_fail_create_vector_embedding_policy_async(self): + return + + async def test_fail_create_full_text_indexing_policy_async(self): + return + + async def test_replace_full_text_policy_async(self): + return + + async def test_replace_full_text_indexing_policy_async(self): + return + + +if __name__ == '__main__': + unittest.main() From 54d3314d2cd9932152fee7dd0b94076ae29bb22b Mon Sep 17 00:00:00 2001 From: simorenoh Date: Fri, 8 Nov 2024 11:46:07 -0500 Subject: [PATCH 2/6] add tests, refine README and changelog --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 2 +- sdk/cosmos/azure-cosmos/README.md | 4 +- .../test/test_full_text_policy.py | 189 +++++++++++++++- .../test/test_full_text_policy_async.py | 202 ++++++++++++++++-- 4 files changed, 372 insertions(+), 25 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index 552c9bd1a280..afafa1698ec6 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -4,7 +4,7 @@ This version and all future versions will support Python 3.13. #### Features Added -* Added full text policy and full text indexing policy. See [PR 37891](https://github.com/Azure/azure-sdk-for-python/pull/37891). +* Added **provisional** full text policy and full text indexing policy. See [PR 37891](https://github.com/Azure/azure-sdk-for-python/pull/37891). * SDK will now retry all ServiceRequestErrors (failing outgoing requests) before failing. Default number of retries is 3. See [PR 36514](https://github.com/Azure/azure-sdk-for-python/pull/36514). * Added Retry Policy for Container Recreate in the Python SDK. See [PR 36043](https://github.com/Azure/azure-sdk-for-python/pull/36043) * Added option to disable write payload on writes. See [PR 37365](https://github.com/Azure/azure-sdk-for-python/pull/37365) diff --git a/sdk/cosmos/azure-cosmos/README.md b/sdk/cosmos/azure-cosmos/README.md index 1a0049e13b80..f2664118d2e5 100644 --- a/sdk/cosmos/azure-cosmos/README.md +++ b/sdk/cosmos/azure-cosmos/README.md @@ -728,7 +728,7 @@ not being able to recognize the new NonStreamingOrderBy capability that makes ve If this happens, you can set the `AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY` environment variable to `"True"` to opt out of this functionality and continue operating as usual.* -### TBD - Full Text Policy and Full Text Indexes +### Public Preview - Full Text Policy and Full Text Indexes We have added new capabilities to utilize full text policies and full text indexing for users to leverage full text search utilizing our Cosmos SDK. These two container-level configurations have to be turned on at the account-level before you can use them. @@ -753,7 +753,7 @@ full_text_policy = { ] } ``` -For all supported languages, see [here](). +Currently, the only supported language is `en-US`. Full text search indexes have been added to the already existing indexing_policy and only require the path to the relevant field to be used. diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py index 370f15cd3143..16145bdbf1a6 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py @@ -31,20 +31,193 @@ def setUpClass(cls): cls.test_db = cls.client.create_database(str(uuid.uuid4())) def test_create_full_text_container(self): - return + # Create a container with a valid full text policy and full text indexing policy + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + indexing_policy = { + "fullTextIndexes": [ + {"path": "/abstract"} + ] + } + created_container = self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = created_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + self.test_db.delete_container(created_container.id) + + # Create a container with a full text policy containing only default language + full_text_policy_no_paths = { + "defaultLanguage": "en-US" + } + created_container = self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_no_paths, + ) + properties = created_container.read() + assert properties["fullTextPolicy"] == full_text_policy_no_paths + self.test_db.delete_container(created_container.id) def test_fail_create_full_text_policy(self): - return + # Pass a full text policy with a wrongly formatted path + full_text_policy_wrong_path = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "abstract", + "language": "en-US" + } + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an invalid Path: abstract" in e.http_error_message - def test_fail_create_full_text_indexing_policy(self): - return + # Pass a full text policy without language attached to the path + full_text_policy_no_langs = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract" + } + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_no_langs + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains invalid syntax" in e.http_error_message + + # Pass a full text policy with an unsupported default language + full_text_policy_wrong_default = { + "defaultLanguage": "spa-SPA", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_default + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an unsupported language spa-SPA. Supported languages are:"\ + in e.http_error_message - def test_replace_full_text_policy(self): - return + # Pass a full text policy with an unsupported path language + full_text_policy_wrong_default = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "spa-SPA" + } + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_default + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an unsupported language spa-SPA. Supported languages are:"\ + in e.http_error_message + + def test_fail_create_full_text_indexing_policy(self): + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + # Pass a full text indexing policy with a path not present in the full text policy + indexing_policy_wrong_path = { + "fullTextIndexes": [ + {"path": "/path"} + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_wrong_path, + full_text_policy=full_text_policy + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The path of the Full Text Index /path does not match the path specified in the Full Text Policy"\ + in e.http_error_message - def test_replace_full_text_indexing_policy(self): - return + # Pass a full text indexing policy with a wrongly formatted path + indexing_policy_wrong_path = { + "fullTextIndexes": [ + {"path": "abstract"} + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_wrong_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "Full-text index specification at index (0) contains invalid path" in e.http_error_message + # Pass a full text indexing policy without a path field + indexing_policy_no_path = { + "fullTextIndexes": [ + {"not_path": "abstract"} + ] + } + try: + self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_no_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "Missing path in full-text index specification at index (0)" in e.http_error_message if __name__ == '__main__': diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py index 0e9be4112c16..4886b926ace6 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py @@ -40,20 +40,194 @@ async def tearDown(self): await self.client.delete_database(self.test_db.id) await self.client.close() - async def test_create_full_text_container_async(self): - return - - async def test_fail_create_vector_embedding_policy_async(self): - return - - async def test_fail_create_full_text_indexing_policy_async(self): - return - - async def test_replace_full_text_policy_async(self): - return - - async def test_replace_full_text_indexing_policy_async(self): - return + async def test_create_full_text_container(self): + # Create a container with a valid full text policy and full text indexing policy + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + indexing_policy = { + "fullTextIndexes": [ + {"path": "/abstract"} + ] + } + created_container = await self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = await created_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + await self.test_db.delete_container(created_container.id) + + # Create a container with a full text policy containing only default language + full_text_policy_no_paths = { + "defaultLanguage": "en-US" + } + created_container = await self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_no_paths, + ) + properties = await created_container.read() + assert properties["fullTextPolicy"] == full_text_policy_no_paths + await self.test_db.delete_container(created_container.id) + + async def test_fail_create_full_text_policy(self): + # Pass a full text policy with a wrongly formatted path + full_text_policy_wrong_path = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "abstract", + "language": "en-US" + } + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an invalid Path: abstract" in e.http_error_message + + # Pass a full text policy without language attached to the path + full_text_policy_no_langs = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract" + } + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_no_langs + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains invalid syntax" in e.http_error_message + + # Pass a full text policy with an unsupported default language + full_text_policy_wrong_default = { + "defaultLanguage": "spa-SPA", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_default + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an unsupported language spa-SPA. Supported languages are:"\ + in e.http_error_message + + # Pass a full text policy with an unsupported path language + full_text_policy_wrong_default = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "spa-SPA" + } + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy_wrong_default + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The Full Text Policy contains an unsupported language spa-SPA. Supported languages are:"\ + in e.http_error_message + + async def test_fail_create_full_text_indexing_policy(self): + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + # Pass a full text indexing policy with a path not present in the full text policy + indexing_policy_wrong_path = { + "fullTextIndexes": [ + {"path": "/path"} + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_wrong_path, + full_text_policy=full_text_policy + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "The path of the Full Text Index /path does not match the path specified in the Full Text Policy"\ + in e.http_error_message + + # Pass a full text indexing policy with a wrongly formatted path + indexing_policy_wrong_path = { + "fullTextIndexes": [ + {"path": "abstract"} + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_wrong_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "Full-text index specification at index (0) contains invalid path" in e.http_error_message + + # Pass a full text indexing policy without a path field + indexing_policy_no_path = { + "fullTextIndexes": [ + {"not_path": "abstract"} + ] + } + try: + await self.test_db.create_container( + id='full_text_container', + partition_key=PartitionKey(path="/id"), + indexing_policy=indexing_policy_no_path + ) + pytest.fail("Container creation should have failed for lack of embedding policy.") + except exceptions.CosmosHttpResponseError as e: + assert e.status_code == 400 + assert "Missing path in full-text index specification at index (0)" in e.http_error_message if __name__ == '__main__': From eaea5c7148b0f406a45ee246d2645bf3035dfdc4 Mon Sep 17 00:00:00 2001 From: simorenoh Date: Fri, 8 Nov 2024 12:00:04 -0500 Subject: [PATCH 3/6] replace tests --- .../test/test_full_text_policy.py | 40 ++++++++++++++++ .../test/test_full_text_policy_async.py | 46 +++++++++++++++++-- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py index 16145bdbf1a6..25c4a2a04a42 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py @@ -70,6 +70,46 @@ def test_create_full_text_container(self): assert properties["fullTextPolicy"] == full_text_policy_no_paths self.test_db.delete_container(created_container.id) + def test_replace_full_text_container(self): + # Replace a container with a valid full text policy and full text indexing policy + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + indexing_policy = { + "fullTextIndexes": [ + {"path": "/abstract"} + ] + } + created_container = self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = created_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + + # Replace the container with new policies + full_text_policy['fullTextPaths'][0]['path'] = "/new_path" + indexing_policy['fullTextIndexes'][0]['path'] = "/new_path" + replaced_container = self.test_db.create_container( + id=created_container.id, + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = replaced_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + self.test_db.delete_container(created_container.id) + def test_fail_create_full_text_policy(self): # Pass a full text policy with a wrongly formatted path full_text_policy_wrong_path = { diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py index 4886b926ace6..ce4bd849002b 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py @@ -40,7 +40,7 @@ async def tearDown(self): await self.client.delete_database(self.test_db.id) await self.client.close() - async def test_create_full_text_container(self): + async def test_create_full_text_container_async(self): # Create a container with a valid full text policy and full text indexing policy full_text_policy = { "defaultLanguage": "en-US", @@ -80,7 +80,47 @@ async def test_create_full_text_container(self): assert properties["fullTextPolicy"] == full_text_policy_no_paths await self.test_db.delete_container(created_container.id) - async def test_fail_create_full_text_policy(self): + async def test_replace_full_text_container_async(self): + # Replace a container with a valid full text policy and full text indexing policy + full_text_policy = { + "defaultLanguage": "en-US", + "fullTextPaths": [ + { + "path": "/abstract", + "language": "en-US" + } + ] + } + indexing_policy = { + "fullTextIndexes": [ + {"path": "/abstract"} + ] + } + created_container = await self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = await created_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + + # Replace the container with new policies + full_text_policy['fullTextPaths'][0]['path'] = "/new_path" + indexing_policy['fullTextIndexes'][0]['path'] = "/new_path" + replaced_container = await self.test_db.create_container( + id=created_container.id, + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = await replaced_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + await self.test_db.delete_container(created_container.id) + + async def test_fail_create_full_text_policy_async(self): # Pass a full text policy with a wrongly formatted path full_text_policy_wrong_path = { "defaultLanguage": "en-US", @@ -166,7 +206,7 @@ async def test_fail_create_full_text_policy(self): assert "The Full Text Policy contains an unsupported language spa-SPA. Supported languages are:"\ in e.http_error_message - async def test_fail_create_full_text_indexing_policy(self): + async def test_fail_create_full_text_indexing_policy_async(self): full_text_policy = { "defaultLanguage": "en-US", "fullTextPaths": [ From 15df7c0db418a3c58948a00416d8362b4b7abd86 Mon Sep 17 00:00:00 2001 From: simorenoh Date: Wed, 13 Nov 2024 18:52:46 -0500 Subject: [PATCH 4/6] update changelog, version --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 4 ++-- sdk/cosmos/azure-cosmos/azure/cosmos/_version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index d727c609b8bd..f9569ca962ad 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -1,9 +1,9 @@ ## Release History -### 4.8.1 (Unreleased) +### 4.9.0 (Unreleased) #### Features Added -* Added **provisional** full text policy and full text indexing policy. See [PR 37891](https://github.com/Azure/azure-sdk-for-python/pull/37891). +* Added full text policy and full text indexing policy. See [PR 37891](https://github.com/Azure/azure-sdk-for-python/pull/37891). #### Breaking Changes diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/_version.py b/sdk/cosmos/azure-cosmos/azure/cosmos/_version.py index fee4c249ab37..5b6088546c61 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/_version.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/_version.py @@ -19,4 +19,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -VERSION = "4.8.1" +VERSION = "4.9.0" From 0ce96df58d549c3b625bf5484c7aa502e63c4d05 Mon Sep 17 00:00:00 2001 From: simorenoh Date: Thu, 14 Nov 2024 16:08:07 -0500 Subject: [PATCH 5/6] update README, tests --- sdk/cosmos/azure-cosmos/README.md | 8 ++++- .../test/test_full_text_policy.py | 26 ++++++++++++++-- .../test/test_full_text_policy_async.py | 30 +++++++++++++++---- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/README.md b/sdk/cosmos/azure-cosmos/README.md index 4899e5e34418..00b19cfa52ce 100644 --- a/sdk/cosmos/azure-cosmos/README.md +++ b/sdk/cosmos/azure-cosmos/README.md @@ -775,7 +775,9 @@ full_text_policy = { ] } ``` -Currently, the only supported language is `en-US`. +Currently, the only supported language is `en-US` - using the relevant ISO-639 language code to ISO-3166 country code. +Any non-supported language or code will return an exception when trying to use it - which will also include the list of supported languages. +This list will include more options in the future; for more information on supported languages, please see [here][cosmos_fts]. Full text search indexes have been added to the already existing indexing_policy and only require the path to the relevant field to be used. @@ -795,6 +797,8 @@ indexing_policy = { ] } ``` +Modifying the index in a container is an asynchronous operation that can take a long time to finish. See [here][cosmos_index_policy_change] for more information. +For more information on using full text policies and full text indexes, see [here][cosmos_fts]. ## Troubleshooting @@ -932,6 +936,8 @@ For more extensive documentation on the Cosmos DB service, see the [Azure Cosmos [cosmos_concurrency_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cosmos/azure-cosmos/samples/concurrency_sample.py [cosmos_index_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cosmos/azure-cosmos/samples/index_management.py [cosmos_index_sample_async]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cosmos/azure-cosmos/samples/index_management_async.py +[cosmos_fts]: https://aka.ms/cosmosfulltextsearch +[cosmos_index_policy_change]: https://learn.microsoft.com/azure/cosmos-db/index-policy#modifying-the-indexing-policy ## Contributing diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py index 25c4a2a04a42..97c37207b405 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py @@ -71,7 +71,13 @@ def test_create_full_text_container(self): self.test_db.delete_container(created_container.id) def test_replace_full_text_container(self): - # Replace a container with a valid full text policy and full text indexing policy + # Replace a container without a full text policy and full text indexing policy + + created_container = self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id") + ) + full_text_policy = { "defaultLanguage": "en-US", "fullTextPaths": [ @@ -86,6 +92,20 @@ def test_replace_full_text_container(self): {"path": "/abstract"} ] } + + # Replace the container with new policies + replaced_container = self.test_db.replace_container( + container=created_container.id, + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = replaced_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + self.test_db.delete_container(created_container.id) + + # Replace a container with a valid full text policy and full text indexing policy created_container = self.test_db.create_container( id='full_text_container' + str(uuid.uuid4()), partition_key=PartitionKey(path="/id"), @@ -99,8 +119,8 @@ def test_replace_full_text_container(self): # Replace the container with new policies full_text_policy['fullTextPaths'][0]['path'] = "/new_path" indexing_policy['fullTextIndexes'][0]['path'] = "/new_path" - replaced_container = self.test_db.create_container( - id=created_container.id, + replaced_container = self.test_db.replace_container( + container=created_container.id, partition_key=PartitionKey(path="/id"), full_text_policy=full_text_policy, indexing_policy=indexing_policy diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py index ce4bd849002b..123e3e12c114 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py @@ -81,7 +81,13 @@ async def test_create_full_text_container_async(self): await self.test_db.delete_container(created_container.id) async def test_replace_full_text_container_async(self): - # Replace a container with a valid full text policy and full text indexing policy + # Replace a container without a full text policy and full text indexing policy + + created_container = await self.test_db.create_container( + id='full_text_container' + str(uuid.uuid4()), + partition_key=PartitionKey(path="/id") + ) + full_text_policy = { "defaultLanguage": "en-US", "fullTextPaths": [ @@ -96,6 +102,20 @@ async def test_replace_full_text_container_async(self): {"path": "/abstract"} ] } + + # Replace the container with new policies + replaced_container = await self.test_db.replace_container( + container=created_container.id, + partition_key=PartitionKey(path="/id"), + full_text_policy=full_text_policy, + indexing_policy=indexing_policy + ) + properties = await replaced_container.read() + assert properties["fullTextPolicy"] == full_text_policy + assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + await self.test_db.delete_container(created_container.id) + + # Replace a container with a valid full text policy and full text indexing policy created_container = await self.test_db.create_container( id='full_text_container' + str(uuid.uuid4()), partition_key=PartitionKey(path="/id"), @@ -109,16 +129,16 @@ async def test_replace_full_text_container_async(self): # Replace the container with new policies full_text_policy['fullTextPaths'][0]['path'] = "/new_path" indexing_policy['fullTextIndexes'][0]['path'] = "/new_path" - replaced_container = await self.test_db.create_container( - id=created_container.id, + replaced_container = await self.test_db.replace_container( + container=created_container.id, partition_key=PartitionKey(path="/id"), full_text_policy=full_text_policy, indexing_policy=indexing_policy ) - properties = await replaced_container.read() + properties = replaced_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] - await self.test_db.delete_container(created_container.id) + self.test_db.delete_container(created_container.id) async def test_fail_create_full_text_policy_async(self): # Pass a full text policy with a wrongly formatted path From 0ec7a6ce98d03d3f09de88934a6f4cfe8a1e6873 Mon Sep 17 00:00:00 2001 From: simorenoh Date: Thu, 14 Nov 2024 16:43:45 -0500 Subject: [PATCH 6/6] additional assertions --- sdk/cosmos/azure-cosmos/test/test_full_text_policy.py | 7 +++++-- .../azure-cosmos/test/test_full_text_policy_async.py | 11 +++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py index 97c37207b405..06aa3203f342 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy.py @@ -77,7 +77,7 @@ def test_replace_full_text_container(self): id='full_text_container' + str(uuid.uuid4()), partition_key=PartitionKey(path="/id") ) - + created_container_properties = created_container.read() full_text_policy = { "defaultLanguage": "en-US", "fullTextPaths": [ @@ -103,6 +103,7 @@ def test_replace_full_text_container(self): properties = replaced_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + assert created_container_properties['indexingPolicy'] != properties['indexingPolicy'] self.test_db.delete_container(created_container.id) # Replace a container with a valid full text policy and full text indexing policy @@ -112,7 +113,7 @@ def test_replace_full_text_container(self): full_text_policy=full_text_policy, indexing_policy=indexing_policy ) - properties = created_container.read() + created_container_properties = created_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] @@ -128,6 +129,8 @@ def test_replace_full_text_container(self): properties = replaced_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + assert created_container_properties['fullTextPolicy'] != properties['fullTextPolicy'] + assert created_container_properties["indexingPolicy"] != properties["indexingPolicy"] self.test_db.delete_container(created_container.id) def test_fail_create_full_text_policy(self): diff --git a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py index 123e3e12c114..2cbf14473c15 100644 --- a/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py +++ b/sdk/cosmos/azure-cosmos/test/test_full_text_policy_async.py @@ -87,7 +87,7 @@ async def test_replace_full_text_container_async(self): id='full_text_container' + str(uuid.uuid4()), partition_key=PartitionKey(path="/id") ) - + created_container_properties = await created_container.read() full_text_policy = { "defaultLanguage": "en-US", "fullTextPaths": [ @@ -113,6 +113,7 @@ async def test_replace_full_text_container_async(self): properties = await replaced_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + assert created_container_properties['indexingPolicy'] != properties['indexingPolicy'] await self.test_db.delete_container(created_container.id) # Replace a container with a valid full text policy and full text indexing policy @@ -122,9 +123,9 @@ async def test_replace_full_text_container_async(self): full_text_policy=full_text_policy, indexing_policy=indexing_policy ) - properties = await created_container.read() - assert properties["fullTextPolicy"] == full_text_policy - assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + created_container_properties = await created_container.read() + assert created_container_properties["fullTextPolicy"] == full_text_policy + assert created_container_properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] # Replace the container with new policies full_text_policy['fullTextPaths'][0]['path'] = "/new_path" @@ -138,6 +139,8 @@ async def test_replace_full_text_container_async(self): properties = replaced_container.read() assert properties["fullTextPolicy"] == full_text_policy assert properties["indexingPolicy"]['fullTextIndexes'] == indexing_policy['fullTextIndexes'] + assert created_container_properties['fullTextPolicy'] != properties['fullTextPolicy'] + assert created_container_properties["indexingPolicy"] != properties["indexingPolicy"] self.test_db.delete_container(created_container.id) async def test_fail_create_full_text_policy_async(self):