【问题标题】:Azure function C#: Create or replace document in cosmos db on HTTP requestAzure 函数 C#:根据 HTTP 请求在 cosmos db 中创建或替换文档
【发布时间】:2019-02-25 12:29:24
【问题描述】:

我正在尝试在 C# 中构建一个 Azure 函数,如果 id 不存在,它会使用 SQL API 在 Azure cosmos DB 中创建一个新的文档对象,如果它已经存在则更新一个文档对象。

这背后的背景是将聊天机器人的对话历史记录到唯一的用户会话中。

输入:
带参数的 HTTP GET 请求(id (string)、chatHistory(string) 和 chatDateTime(string))

输出:
如果已经存在具有相同 ID 的文档对象 - 然后使用输入 chatHisotry 和 chatDateTime 更新文档。

如果不存在具有相同 id 的文档对象,则创建一个新的文档对象,其 id、chatHistory 和 chatDateTime 等于输入。

非常感谢任何帮助!这几天一直在苦苦挣扎。

文档对象示例:

{
    "id": "ESCRfAKwlTbH8W5aVRLxgA",
    "chatHistory": "Hi, Hello",
    "chatDateTime": "Fri Sep 21 2018 05:34:35 GMT+0000 (Coordinated Universal Time)",
    "_rid": "RwYSAIqaSVg2AAAAAAAAAA==",
    "_self": "dbs/RwYSAA==/colls/RwYSAIqaSVg=/docs/RwYSAIqaSVg2AAAAAAAAAA==/",
    "_etag": "\"00007400-0000-0000-0000-5ba482ed0000\"",
    "_attachments": "attachments/",
    "_ts": 1537508077
}

【问题讨论】:

  • 您是在直接的 azure 门户或 Visual Studio 中开发它。?
  • 你能告诉我们你到目前为止做了什么吗?你尝试过什么,你正在努力解决什么问题?
  • 嗨!我正在直接 Azure 门户上开发它。
  • @NickChapsas 我一直在搞乱下面的这个(我在网上找到的随机教程),它可以让我将文档插入到 cosmos 文档数据库中。 github.com/MicrosoftDocs/azure-docs/blob/master/articles/… 但没有运气在其中构建条件逻辑
  • @NickChapsas 我已经设法构建了一个函数,可以根据 http get 请求将数据输入到 cosmos 文档数据库中,但是如果文档对象,我正在努力使函数 replace/upsert(?) 数据已经存在

标签: c# function azure azure-cosmosdb document


【解决方案1】:

您可以使用 Azure Functions 的Cosmos DB Output Binding。输出绑定执行 Upsert 操作。

[FunctionName("HttpTriggerWithSingleDocument")]
    public static async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
        [DocumentDB(databaseName: "your-db",
            collectionName: "your-collection",
            ConnectionStringSetting = "CosmosDBConnectionString")] out dynamic documentToSave)
    {
        dynamic data = await req.Content.ReadAsAsync<object>();

        if (data == null)
        {
            documentToSave = null;
            return req.CreateResponse(HttpStatusCode.BadRequest);
        }

        documentToSave = data;

        return req.CreateResponse(HttpStatusCode.Created);
}

Azure 门户版本:

using System.Net;

public static async Task<HttpResponseMessage> Run(
            HttpRequestMessage req,
            IAsyncCollector<dynamic> documentsToStore)
        {
            dynamic data = await req.Content.ReadAsAsync<object>();

            if (data == null)
            {
                return req.CreateResponse(HttpStatusCode.BadRequest);
            }

            await documentsToStore.AddAsync(data);

            return req.CreateResponse(HttpStatusCode.Created);
    }

您还需要将function.json 更新为:

{
  "bindings": [
    {
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "documentsToStore",
      "databaseName": "<your-database-name>",
      "collectionName": "<your-collection-name>",
      "createIfNotExists": false,
      "connection": "<your-connection-setting-name>",
      "direction": "out"
    }
  ]
}

更多示例在这里:https://github.com/ealsur/serverless-recipes/tree/master/cosmosdboutputbindings

【讨论】:

  • 嗨 Matias,我已将您的代码复制并粘贴到一个名为“HttpTriggerWithSingleDocument”的新天蓝色函数中,并且我已将我的 cosmos db 添加为输出,但我遇到了此错误 (textuploader.com/dvyxe) .我正在天蓝色的门户中构建它。你有什么建议吗?对不起,如果我的问题很菜鸟! C# 和 API 构建对我来说仍然是新事物。
  • @Michael 在使用 Azure 门户时,语法略有不同。我编辑了我的答案以包含它。
  • 谢谢马蒂亚斯!这行得通!对于其他人测试这个 - 我必须做的唯一改变是添加我的数据库配置并在我的functions.json中将“类”更改为“req”。
【解决方案2】:

这是一个如何做到这一点的例子。您只需要根据需要进行调整即可。

    [FunctionName("Function1")]
    public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
    TraceWriter log)
    {
        dynamic data = await req.Content.ReadAsAsync<object>();

        var connectionString = "DbUri";
        var key = "DbKey";

        using (var client = new DocumentClient(new Uri(connectionString), key))
        {
            var collectionLink = UriFactory.CreateDocumentCollectionUri("DbName", "CollectionName");
            await client.UpsertDocumentAsync(collectionLink, data);
        }

        return req.CreateResponse(HttpStatusCode.OK);
    }

【讨论】:

  • 不建议在Function的代码中创建DocumentClients,这会导致Socket Exhaustion,见github.com/Azure/azure-functions-host/wiki/Managing-Connections
  • 好点,很高兴知道。我忘记了。它还取决于应用程序计划。但是在那个链接中是如何使用 DocumentClient 的很好的例子,所以把它添加到我的例子中,我们就有了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多