3

We have a customer device data usage document (e.g. with name "ABC_XYZ") that when customer deprovision device, should be archived for analytical purpose. The solution is to create another document (e.g. with name "ABC_XYZ_09252017_1748") and delete current one (same document will hold more data in future when device is provisioned again).

To achieve this, I was hoping to find a method in SDK but could not find any. Only Create (CreateDocumentAsync) and Replace (ReplaceDocumentAsync).

I could create a new one with new name and then copy data from old one into new one and then delete the old one. Wondering is there one single API e.g. CopyDocumentAsync or any other better way to achieve this?

2 Answers 2

3

There is no "copy document" API call (or related SDK call). You'd need to read the current document (which you can do with a direct read, vs a query), then create a new document (followed by deleting the original).

If you want this to occur atomically, you would need to put the query + write + delete into a stored procedure (which treats its operations as a single transaction).

Alternatively, you could leave your original document intact and mark it as deleted (with an additional property), and then filter on that property when doing your normal reads/queries.

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

3 Comments

Thank you for suggestions, last one is not feasible as the same document in future may be used for holding new data. Also all of this logic needs to go in a WebAPI method. I am not sure stored proc is feasible there?
Calling a Cosmos DB stored procedure is just about the same level of effort as calling any other Cosmos DB operation. I don't see why it would be an issue calling from a WebAPI method (and it would be one call, vs 3 calls for read+write+delete).
Ok will definitely try this. Thank you.
3

Here's an example of how you might implement this as a stored procedure:

function storedProcedure(copyDocId) {
  let context = getContext();
  let response = context.getResponse();
  let collection = context.getCollection();
  let collectionLink = collection.getAltLink();

  let documentLink = collection.getAltLink() + "/docs/" + copyDocId;

  let canRead = collection.readDocument(documentLink, {}, readDocumentCallback);
  if (!canRead) throw "Unable to check for existence of document";

  function readDocumentCallback(err, doc, responseOptions) {
    if (err) throw err;
    doc.id = doc.id + 'XYZ'; // or however you determine this

    let canDelete = collection.deleteDocument(documentLink, {},
      function (err, deleted) {
        if (err) throw err;

        let canCreate = collection.createDocument(collectionLink, doc,
          function (err, newDoc) {
            if (err) throw err;

            response.setBody(newDoc);
          }
        );

        if (!canCreate) throw "Unable to create copy";
      }
    );

    if (!canDelete) throw "Unable to delete old document";
  }
}

Once the SPROC has been added to your collection, invoking it from your WebAPI is simple:

var sprocUri = UriFactory.CreateStoredProcedureUri(databaseId, collectionId, sprocName);
var newDoc await documentClient.ExecuteStoredProcedureAsync<dynamic>(sprocUri, idOfDocToCopy);

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.