5

In this SO question I had learnt that I cannot delete a Cosmos DB document using SQL.

Using Python, I believe I need the DeleteDocument() method. This is how I'm getting the document ID's that are required (I believe) to then call the DeleteDocument() method.

# set up the client
client = document_client.DocumentClient()

# use a SQL based query to get a bunch of documents
query = { 'query': 'SELECT * FROM server s' }
result_iterable = client.QueryDocuments('dbs/DB/colls/coll', query, options)

results = list(result_iterable);

for x in range(0, len (results)):
    docID = results[x]['id']

Now, at this stage I want to call DeleteDocument(). The inputs into which are document_link and options.

I can define document_link as something like

document_link = 'dbs/DB/colls/coll/docs/'+docID

And successfully call ReadAttachments() for example, which has the same inputs as DeleteDocument().

When I do however, I get an error...

The partition key supplied in x-ms-partitionkey header has fewer
components than defined in the the collection

...and now I'm totally lost

UPDATE

Following on from Jay's help, I believe I'm missing the partitonKey element in the options.

In this example, I've created a testing database, it looks like this Screen grab from my Azure account

So I think my partition key is /testPART

When I include the partitionKey in the options however, no results are returned, (and so print len(results) outputs 0).

Removing partitionKey means that results are returned, but the delete attempt fails as before.

# Query them in SQL
query = { 'query': 'SELECT * FROM c' }

options = {}
options['enableCrossPartitionQuery'] = True
options['maxItemCount'] = 2
options['partitionKey'] = '/testPART'
result_iterable = client.QueryDocuments('dbs/testDB/colls/testCOLL', query, options)
results = list(result_iterable)

# should be > 0
print len(results)

for x in range(0, len (results)):
    docID = results[x]['id']
    print docID
    client.DeleteDocument('dbs/testDB/colls/testCOLL/docs/'+docID, options=options)
    print 'deleted', docID

2 Answers 2

7

According to your description, I tried to use pydocument module to delete document in my azure document db and it works for me.

Here is my code:

import pydocumentdb;
import pydocumentdb.document_client as document_client

config = {
    'ENDPOINT': 'Your url',
    'MASTERKEY': 'Your master key',
    'DOCUMENTDB_DATABASE': 'familydb',
    'DOCUMENTDB_COLLECTION': 'familycoll'
};

# Initialize the Python DocumentDB client
client = document_client.DocumentClient(config['ENDPOINT'], {'masterKey': config['MASTERKEY']})

# use a SQL based query to get a bunch of documents
query = { 'query': 'SELECT * FROM server s' }

options = {}
options['enableCrossPartitionQuery'] = True
options['maxItemCount'] = 2

result_iterable = client.QueryDocuments('dbs/familydb/colls/familycoll', query, options)

results = list(result_iterable);

print(results)

client.DeleteDocument('dbs/familydb/colls/familycoll/docs/id1',options)

print 'delete success'

Console Result:

[{u'_self': u'dbs/hitPAA==/colls/hitPAL3OLgA=/docs/hitPAL3OLgABAAAAAAAAAA==/', u'myJsonArray': [{u'subId': u'sub1', u'val': u'value1'}, {u'subId': u'sub2', u'val': u'value2'}], u'_ts': 1507687788, u'_rid': u'hitPAL3OLgABAAAAAAAAAA==', u'_attachments': u'attachments/', u'_etag': u'"00002100-0000-0000-0000-59dd7d6c0000"', u'id': u'id1'}, {u'_self': u'dbs/hitPAA==/colls/hitPAL3OLgA=/docs/hitPAL3OLgACAAAAAAAAAA==/', u'myJsonArray': [{u'subId': u'sub3', u'val': u'value3'}, {u'subId': u'sub4', u'val': u'value4'}], u'_ts': 1507687809, u'_rid': u'hitPAL3OLgACAAAAAAAAAA==', u'_attachments': u'attachments/', u'_etag': u'"00002200-0000-0000-0000-59dd7d810000"', u'id': u'id2'}]
delete success

Please notice that you need to set the enableCrossPartitionQuery property to True in options if your documents are cross-partitioned.

Must be set to true for any query that requires to be executed across more than one partition. This is an explicit flag to enable you to make conscious performance tradeoffs during development time.

You could find above description from here.


Update Answer:

I think you misunderstand the meaning of partitionkey property in the options[].

For example , my container is created like this:

enter image description here

My documents as below :

{
    "id": "1",
    "name": "jay"
}

{
    "id": "2",
    "name": "jay2"
}

My partitionkey is 'name', so here I have two paritions : 'jay' and 'jay1'.

So, here you should set the partitionkey property to 'jay' or 'jay2',not 'name'.

Please modify your code as below:

 options = {}
    options['enableCrossPartitionQuery'] = True
    options['maxItemCount'] = 2
    options['partitionKey'] = 'jay' (please change here in your code)

    result_iterable = client.QueryDocuments('dbs/db/colls/testcoll', query, options)
    results = list(result_iterable);

    print(results)

Hope it helps you.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Jay, unfortunately that doesn't work for me - passing in those options with enableCrossPartitionQuery as True or False - error is in the same as in the question
@BenMayo It's werid. The above code works well for me.If you try it completely,would you please update general structure of your database to let me help you solve this issue? In,addition, you could refer to this case:stackoverflow.com/questions/42999586/…
@BenMayo Any concern,please let me know.
1

Using the azure.cosmos library:

install and import azure cosmos package:

from azure.cosmos import exceptions, CosmosClient, PartitionKey

define delete items function - in this case using the partition key in query:

def deleteItems(deviceid):
    client = CosmosClient(config.cosmos.endpoint, config.cosmos.primarykey)

    # Create a database if not exists
    database = client.create_database_if_not_exists(id=azure-cosmos-db-name)

    # Create a container
    # Using a good partition key improves the performance of database operations.
    container = database.create_container_if_not_exists(id=container-name, partition_key=PartitionKey(path='/your-pattition-path'), offer_throughput=400)

    #fetch items
    query = f"SELECT * FROM c WHERE c.device.deviceid IN ('{deviceid}')"
    items = list(container.query_items(query=query, enable_cross_partition_query=False))
    for item in items:
        container.delete_item(item, 'partition-key')

usage:

deviceid=10
deleteItems(items)

github full example here: https://github.com/eladtpro/python-iothub-cosmos

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.