批量更新DocumentDB中的数据

时间:2016-01-12 19:20:03

标签: azure-cosmosdb

我希望将一个默认值的属性添加到我通过SELECT查询检索的一组文档中,如果它们不包含任何值。

我在两个方面考虑这个问题:

  1. SELECT * FROM c article WHERE article.details.locale =' en-us'
  2. 我想查找article.details.x 不存在的所有文章。

    1. 添加属性,article.details.x = true
    2. 我希望通过Azure门户可以支持此EXEC命令,因此我不必创建一个迁移工具来运行此命令,但我无法在门户中找到此选项。这可能吗?

2 个答案:

答案 0 :(得分:6)

您可以使用Azure Document DB Studio作为创建和执行存储过程的前端。它可以找到here。它很容易设置和使用。

我根据你的例子模拟了一个存储过程:

function updateArticlesDetailsX() {

   var collection = getContext().getCollection();
   var collectionLink = collection.getSelfLink();
   var response = getContext().getResponse();
   var docCount = 0;
   var counter = 0;

   tryQueryAndUpdate();

   function tryQueryAndUpdate(continuation) {
        var query = {
            query: "select * from root r where IS_DEFINED(r.details.x) != true"
        };

        var requestOptions = {
            continuation: continuation
        };

        var isAccepted =
            collection
            .queryDocuments(collectionLink,
                            query,
                            requestOptions,
                            function queryCallback(err, documents, responseOptions) {
                                     if (err) throw err;
                                     if (documents.length > 0) {
                                        // If at least one document is found, update it.
                                        docCount = documents.length;
                                        for (var i=0; i<docCount; i++){
                                            tryUpdate(documents[i]);
                                        }
                                        response.setBody("Updated " + docCount + " documents");
                                      }
                                      else if (responseOptions.continuation) {
                                          // Else if the query came back empty, but with a continuation token; 
                                          // repeat the query w/ the token.
                                        tryQueryAndUpdate(responseOptions.continuation);
                                      } else {
                                             throw new Error("Document not found.");
                                             }
                            });

        if (!isAccepted) {
            throw new Error("The stored procedure timed out");
        }
    }

    function tryUpdate(document) {
        //Optimistic concurrency control via HTTP ETag.
        var requestOptions = { etag: document._etag };

        //Update statement goes here:
        document.details.x = "some new value";

        var isAccepted = collection
                         .replaceDocument(document._self,
                                          document,
                                          requestOptions,
                                          function replaceCallback(err, updatedDocument, responseOptions) {
                                                   if (err) throw err;
                                                   counter++;
                                           });

        // If we hit execution bounds - throw an exception.
        if (!isAccepted) {
            throw new Error("The stored procedure timed out");
        }
    }
}

我从Andrew GitHub获得了此代码的粗略轮廓。

这个大纲应该接近你需要做的。

答案 1 :(得分:5)

DocumentDB无法在单个查询中更新大量文档。但是,门户网站确实有一个脚本资源管理器,允许您针对单个集合编写和执行存储过程。 Here是一个示例sproc,它将查询与replaceDocument命令相结合,以更新一些文档,您可以将这些文档用作编写自己的文档的起点。需要牢记的是,DocumentDB不允许sprocs运行超过5秒(使用一些缓冲区)。所以你可能需要多次运行你的sproc并跟踪你已经完成的事情,如果它不能在一个5秒的运行中完成。在您的查询中使用IS_DEFINED(collection.field.subfield)!= true(感谢@cnaegle)后跟定义该字段的文档替换(或删除该文档)应该允许您根据需要多次运行sproc

如果您不想编写sproc,最简单的方法是使用DocumentDB数据迁移工具导出数据库。将其导入Excel以操作或编写脚本以进行操作。然后使用数据迁移工具再次上传它。