How to show unique keys on Cosmos DB container? - azure

This link implies that unique keys can be seen in a Cosmos DB container by looking at the settings. However I can't seem to find them using both the portal and the storage explorer. How can you view the unique keys on an existing Cosmos DB container? I have a document that fails to load due to a key violation which should be impossible so I need to confirm what the keys are.

A slightly easier way to view your Cosmos DB unique keys is to view the ARM template for your resource.
On your Cosmos DB account, click Settings/ Export Template- let the template be generated and view online once complete. You will find them under the "uniqueKeyPolicy" label.

Based on this blob, unique keys policy should be visible like below:
"uniqueKeyPolicy": {
"uniqueKeys": [
{
"paths": [
"/name",
"/country"
]
},
{
"paths": [
"/users/title"
]
}
]
}
However, I could not see it on the portal as same as you. Maybe it's a bug here.
You could use cosmos db sdk as a workaround to get the unique keys policy, please see my java sample code.
ResourceResponse<DocumentCollection> response1 = documentClient.readCollection("dbs/db/colls/test", null);
DocumentCollection coll =response1.getResource();
UniqueKeyPolicy uniqueKeyPolicy = coll.getUniqueKeyPolicy();
Collection<UniqueKey> uniqueKeyCollections = uniqueKeyPolicy.getUniqueKeys();
for(UniqueKey uniqueKey : uniqueKeyCollections){
System.out.println(uniqueKey.getPaths());
}

Here is the basic code that worked for me. The code that writes the collection is output in Json format. I think this is similar to what you see in the portal but it skips or omits the uniqueKeyPolicy information.
As a side note I think I found a bug or odd behavior. Inserting a new document can throw unique index constraint violation but updates do not.
this.EndpointUrl = ConfigurationManager.AppSettings["EndpointUrl"];
this.PrimaryKey = ConfigurationManager.AppSettings["PrimaryKey"];
string dbname = ConfigurationManager.AppSettings["dbname"];
string containername = ConfigurationManager.AppSettings["containername"];
this.client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey);
DocumentCollection collection = await client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(dbname, containername));
Console.WriteLine("\n4. Found Collection \n{0}\n", collection);

Support for showing unique key policy in collection properties will be added soon. Meanwhile you can use DocumentDBStudio to see unique keys in collection. Once unique key policy is set, it cannot be modified.
WRT odd behavior, can you please share full isolated repro and explain expected and actual behavior.

Here you can view the ARM template in your Azure Portal, and as the winner comment says You will find the unique keys under the "uniqueKeyPolicy" label.

Related

Why does my Azure Cosmos DB SQL API Container Refuse Multiple Items With Same Partition Key Value?

In Azure Cosmos DB (SQL API) I've created a container whose "partition key" is set to /part_key and I am now trying to create and edit data in Data Explorer.
I created an item that looks like this:
{
"id": "test_id",
"value": "val000",
"magicNumber": 32,
"part_key": "asdf"
}
I am now trying to create an item that looks like this:
{
"id": "frank",
"value": "val001",
"magicNumber": 33,
"part_key": "asdf"
}
Based on the documentation I believe that each item within a partition key needs a distinct id, which to me implies that multiple items can in fact share a partition key, which makes a lot of sense.
However, I get an error when I try to save this second item:
{"code":409,"body":{"code":"Conflict","message":"Entity with the specified id already exists in the system...
I see that if I change the value of part_key to something else (say asdf2), then I can save this new item.
Either my expectations about this functionality are wrong, or else I'm doing this wrong somehow. What is wrong here?
Your understanding is correct, It could happen if you are trying to instead a new document with id equal to id of the existing document. This is not allowed, so operation fails.
Before you insert the modified copy, you need to assign a new id to it. I tested the scenario and it looks fine. May be try to create a new document and check

Comparing data in an Azure Index to data that is about to be uploaded

I have an index using the Azure Cognitive Search service. I'm writing a program to automate the upload of new data to this index. I don't want to delete and re-create the index from scratch unnecessarily each time. Is there a way of comparing what is currently in the index with the data that I am about to upload, without having to download that data from there first and manually compare it? I have been looking at the MS documentation and other articles but cannot see a way to do this comparison?
you can use MergeOrUpload operation, so if it's not there it will insert, otherwise update.
Please make sure the IDs are the same otherwise you'll endup always adding new items.
IndexAction.MergeOrUpload(
new Customer()
{
Id = "....",
UpdatedBy = new
{
Id = "..."
}
}
)
https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.search.models.indexactiontype?view=azure-dotnet

How to delete a document from a collection in cosmos db using Java?

How can I delete a document from a collection.
AsyncDocumentClient client = getDBClient();
RequestOptions options = new RequestOptions();
options.setPartitionKey(new PartitionKey("143003"));
client.deleteDocument(String.format("dbs/test-lin/colls/application/docs/%s", document.id()), options);
I am trying to delete a set of documents from collection based on some condition. I have set the partition key. The read-write keys are being used (So no permission issue).
There are no errors when executing this code. The document is not getting deleted from the collection.
How to fix the issue?
#Suj Patil
You should call subscribe(). The publisher does not do anything until some one subscribes.
client.deleteDocument(String.format("dbs/test-lin/colls/application/docs/%s", document.id()), options).subscribe()

Getting database names from server

I want to do a simple thing: get the database names on a RavenDB server. Looks straightforward according to the docs (https://ravendb.net/docs/article-page/4.1/csharp/client-api/operations/server-wide/get-database-names), however I'm facing a chicken-and-egg problem.
The problem comes because I want to get the database names without knowing them in advance. The code in the docs works great, but requires to have an active connection to a DocumentStore. And to get an active connection to a DocumentStore, is mandatory to select a valid database. Otherwise I can't execute the GetDatabaseNamesOperation.
That makes me think that I'm missing something. Is there any way to get the database names without having to know at least one of them?
The database isn't mandatory to open a store. Following code works with no problems:
using (var store = new DocumentStore
{
Urls = new[] { "http://live-test.ravendb.net" }
})
{
store.Initialize();
var dbs = store.Maintenance.Server.Send(new GetDatabaseNamesOperation(0, 25));
}
We send GetDatabaseNamesOperation to the ServerStore, which is common for all databases and holds common data (like database names).

Cloud Datastore Projection Query with filters with AppEngine NodeJS Standard

I am learning GCP, and have searched through the documentation. The Projection queries documentation states that they can be used with filters albeit with some limitations. As far as I understand I am not falling within the limitations, but still I cannot make it work.
What I want to do is a simple
SELECT property FROM kind WHERE enabled = TRUE
The properties are marked as indexed, I have also deployed an index.yaml. And my code is the following
const selectQuery = programTypeQuery
.select(entityNameProperty)
.filter('enabled',true);
When commenting the select line, the query works. When commenting the filter line, it also works, but when running both I get the following message in postman.
{
"code": 9,
"metadata": {
"_internal_repr": {}
},
"note": "Exception occurred in retry method that was not classified as transient"
}
My log just shows a 400 status error.
Any help will be appreciated
EDIT:
this is the full code. I have a parameter that indicates the language of the name. in the database I have nameEn and nameEs as properties, so I want to return only the name in the selected language. enabled is a boolean property that indicates if the product is active or not.
const Datastore = require('#google-cloud/datastore');
const datastore = Datastore();
const programTypeQuery = datastore.createQuery('programType')
entityNameProperty = 'name' + req.params.languageCode
const selectQuery = programTypeQuery
.select(entityNameProperty)
.filter('enabled',true);
selectQuery.runQuery()
.then((results) => {
res.json(results);
})
.catch(err => res.status(400).json(err));
From the details you provided it is hard to detect where this issue is being originated. Can you use Google APIs Explorer for Datastore API and try your query. I prepared the request body according to your descriptions, you can click here and execute it by just changing the projectId. By doing this you will receive a sucessful response or an error message with details, it might be easier to detect the root cause from here.
Most likely you are missing a composite index definition. You should be able to look at your GAE logs in stackdriver to see the error message returned from Cloud Datastore.
Since your property name is dynamic you won't be able to use a composite index effectively. You'll probably need to change your data model to something that doesn't use dynamic property names.

Resources