我尝试使用DocumentClient从AzureFunction运行以下查询:
SELECT
*
FROM
c
where
ARRAY_CONTAINS(
c.facilities,
{ \"id\": \"d742df06-5343-44cf-55b5-bce660ccb907\" },
true
)
(为了便于阅读,此处添加了换行符)
如果我从Azure门户中的查询资源管理器运行此查询,它可以很好地工作。
如果我从Azure Function运行它,我会得到以下异常:
{
"errors":[
{
"severity":"Error",
"location":{
"start":22,
"end":106
},
"code":"SC2050",
"message":"The ARRAY_CONTAINS function requires 2 argument(s)."
}
]
}
我个人认为,这是从Azure功能运行的事实是无关紧要的 - 虽然我没有必要从本地运行的应用程序尝试它,我相信我会得到相同的响应,因为它似乎这个错误来自DocumentClient或DocumentDb SQL引擎本身。我在同一个项目中运行了另一个Azure CosmosDbTrigger函数,唯一的区别是触发函数和查询本身的集合 - 另一个不使用ARRAY_CONTAINS()。
上面的查询是直接从QuerySpec对象(来自调试器)复制的,我将进入以下方法:
dbClient.CreateDocumentQuery<Document>(uri, query)
我已经确认uri对我的集合有正确的URI,查询包含上面的查询。我目前将文档中的ID值传递给Azure Functions触发器,替换为您在上面看到的硬编码值。
我试图使用ARRAY_CONTAINS的三参数形式,因为我只需要ID值来匹配。
为什么我收到此错误的任何想法?
更新#1
好的,我决定打开我的方便花花公子的LinqPad副本并编写一个小程序来测试相同的代码。我将Azure函数中的相关代码行复制并粘贴到LinqPad中并尝试运行它。这次它像冠军一样工作。
所以这似乎从方程中删除了DocumentClient,至少从本地机器中删除了。关于为什么它会在Azure函数中爆炸的任何想法?
更新2
这是功能代码的略微编辑版本。要在此发布,我已经更改了类中某些静态变量的值。除此之外,这与生成下面的调试器输出的代码相同。
public static class DeleteItem
{
private static string OtherCollection = "MyOtherCollection";
private static string MainCollection = "MainCollection";
[FunctionName("DeleteItem")]
public static async Task Run(
[CosmosDBTrigger(
"myDb",
"MainCollection",
ConnectionStringSetting = "DocDbConnectionString"
)] IReadOnlyList<Document> documents,
TraceWriter log)
{
try
{
using (var dbClient = new DocumentClient(new Uri(Config.DocDbEndpoint), Config.DocDbKey))
{
foreach (var doc in documents)
{
// Get the ID of the document
var itemId = doc.Id;
try
{
// Determine if the doc should be deleted
var isDeleted = doc.GetPropertyValue<bool?>("isDeleted");
if (!isDeleted.HasValue || !isDeleted.Value) continue;
// Query the other collection to see if this item is being used
var uri = UriFactory.CreateDocumentCollectionUri(Config.DocDbName, OtherCollection);
var paramsList = new SqlParameterCollection {
new SqlParameter
{
Name = "@itemId",
Value = itemId
}
};
var query = new SqlQuerySpec("SELECT * FROM c where ARRAY_CONTAINS(c.facilities, { id: @itemId }, true)", paramsList);
var result = dbClient.CreateDocumentQuery<Document>(uri, query).ToList();
// If the item wasn't found in the other collection, then go ahead and completely remove it
if (!result.Any())
{
uri = UriFactory.CreateDocumentUri(Config.DocDbName, MainCollection, itemId);
await dbClient.DeleteDocumentAsync(uri);
log.Info($"Item (Id = {itemId}) has been completely removed from the database.");
}
// Otherwise just log that we're keeping this as a soft-delete
else
{
log.Info($"Item (Id = {itemId}) stored as soft-delete.");
}
}
catch (Exception ex)
{
log.Error($"Unable to delete item (Id = {itemId})", ex);
}
}
}
}
catch (Exception ex)
{
log.Error("Unable to perform delete operation", ex);
}
}
}
在调试器中运行我在查询执行(未编辑)之前看到以下内容:
运行查询后,控制传递到catch块,我得到以下内容(未经编辑):
以下是该例外(未经编辑)的一些细节:
Exception Message: {"errors":[{"severity":"Error","location":{"start":22,"end":75},"code":"SC2050","message":"The ARRAY_CONTAINS function requires 2 argument(s)."}]}
Inner Exception Message: Exception from HRESULT: 0x800A0B00
Stack Trace:
at Microsoft.Azure.Documents.Query.QueryPartitionProvider.GetPartitionedQueryExecutionInfoInternal(SqlQuerySpec querySpec, PartitionKeyDefinition partitionKeyDefinition, Boolean requireFormattableOrderByQuery, Boolean isContinuationExpected)
at Microsoft.Azure.Documents.Query.DocumentQueryExecutionContextBase.<GetPartitionedQueryExecutionInfoAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Documents.Query.DocumentQueryExecutionContextFactory.<CreateDocumentQueryExecutionContextAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Documents.Linq.DocumentQuery`1.<CreateDocumentQueryExecutionContextAsync>d__12.MoveNext()
如果我接受该查询并且Id和我将它们转储到Azure Portal的查询资源管理器中,我会得到以下结果(通过删除ID值和一个人的名字来编辑):
此时,我有点沮丧。我已经尝试过调整查询字符串,确保它不像一个额外的引用,不匹配的引号或类似的其他奇怪的东西。我在这里没有想法。