azure x-ms-partitionkey标头中提供的分区键的组件比集合中定义的少

szqfcxe2  于 2023-11-21  发布在  其他
关注(0)|答案(1)|浏览(98)

我尝试使用PowerShell向Azure中的Cosmos DB API发送请求,但我不断从服务返回以下错误:
“x-ms-partitionkey标头中提供的分区键的组件少于集合中定义的组件。”
当我使用x-ms-documentdb-partitionkey头时也是如此,无论我尝试GET(读取)请求,还是尝试POST/PUT(创建/更新)文档,都会发生这种情况。如果我尝试发送空数组的值,或者带有单个空字符串的数组,或者枚举“None”,我都会得到一条错误消息“分区键None无效”(或者我给出的任何值)。
但是,我的集合是在需要分区键之前创建的,所以我的集合最初没有分区键。在迁移数据库之后,集合设置选项卡显示“分区键”值/_partitionKey,启用了大分区键。还有一个注意,容器是非分层分区的。但是,我的文档都没有属性“_partitionKey”,一个都没有价值
如何使用原生PowerShell处理Cosmos API?

njthzxwz

njthzxwz1#

经过大量的搜索和尝试/错误,我终于能够得到一些工作。随意使用这个为您自己的PowerShell需要。

认证

首先,您需要进行身份验证。您可以硬编码访问密钥,也可以使用以下命令动态检索它。

$keys = Invoke-AzResourceAction -Action "listkeys" `
    -ResourceType "Microsoft.DocumentDb/databaseAccounts" `
    -ResourceGroupName $rgName `
    -Name $cosmosAccountName `
    -ApiVersion "2015-04-08" `
    -Force

$keys.primaryMasterKey            # Use this one for writing.
$keys.primaryReadonlyMasterKey    # Use this one for reading.

字符串
你需要获取这个密钥,并生成一个认证头。但是要做到这一点,你需要知道你将对哪个URL发出请求,以及什么动词(例如POST,PUT等)。
如果您正在执行查询,则您的ResourceLink将是集合文档(例如dbs/myDatabase/colls/myCollection/docs)。如果您正在创建或更改文档,则您的ResourceLink将是特定文档(例如dbs/myDatabase/colls/myCollection/docs/myDocGUID)。在这两个示例中,您的ResourceType将是docs

# Credit from this URL: https://sql-articles.com/articles/azure/cosmos-db/provisioning-azure-cosmos-db-using-powershell/

function Generate-MasterKeyAuthorizationSignature {
    [CmdletBinding()]
    [OutputType([string])]
    Param (
        # The HTTP verb going to be used with this authorization signature.  Can choose from 'DELETE', 'GET', 'PATCH', 'POST', or 'PUT'.
        [Parameter(Mandatory)]
        [ValidateSet("DELETE", "GET", "PATCH", "POST", "PUT")]
        [string] $Verb,

        # The access key to use for authentication to the target.
        [Parameter(Mandatory)]
        [string] $Key,

        # Optional Parameter.  The link of the resource we are requesting access to (e.g. dbs/myDatabase/colls/myCollection/docs/myDocID).
        [Parameter()]
        [string] $ResourceLink = [string]::Empty,

        # Optional Parameter.  The type of resource we are requesting access to (e.g. docs).
        [Parameter()]
        [string] $ResourceType = [string]::Empty,

        # Optional Parameter.  The date and time to attach to this signature.  Default value is right now, UTC.
        [Parameter()]
        [string] $DateTime = ([DateTime]::UtcNow.ToString("r")),

        # Optional Parameter.  The type of key the Key value represents.  Default value is 'master'.
        [Parameter()]
        [string] $KeyType = "master",

        # Optional Parameter.  The algorithm version that was used to generate the key (e.g. 1.0).  Default value is '1.0'.
        [Parameter()]
        [string] $TokenVersion = "1.0"
    )

    Process {
        $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
        $hmacSha256.Key = [System.Convert]::FromBase64String($Key)
        if ($ResourceLink -eq $ResourceType) {
            $ResourceLink = [string]::Empty
        }

        $payload = "$($Verb.ToLowerInvariant())`n$($ResourceType.ToLowerInvariant())`n$ResourceLink`n$($DateTime.ToLowerInvariant())`n`n"
        $hashPayload = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payload))
        $signature = [System.Convert]::ToBase64String($hashPayload)
        return [System.Web.HttpUtility]::UrlEncode("type=$KeyType&ver=$TokenVersion&sig=$signature")
    }
}


如果声明并调用上面的函数,您将获得authorization头所需的值。

头部

$headers = @{
    authorization         = $authSig
    "x-ms-date"           = $dateTime
    "x-ms-version"        = "2020-07-15"
    "x-ms-max-item-count" = 100
}    # Shared headers used by all requests.


如果您正在查询数据,则需要以下标题(除了上面的标题之外):

如果您正在更改数据,您将需要以下标题(除了共享):

  • x-ms-documentdb-partitionkey: []您的内容类型将为application/json。如果您不使用分区,或从无分区集合迁移,请将空数组[]设置为您的分区键。否则,给予一个数组,其中包含单个字符串和您的分区键(目前他们只支持一次使用一个)。

Body

如果你正在查询数据,你的主体将是一个包含查询的JSON主体。如果需要,你也可以使用参数,作为一个单独的JSON属性。

$body = @{
    query = "select * from C"
}


如果您正在更改数据,您的主体将是整个文档(在创建或替换时)或patch operation

$body = @{
    operations = @(
        @{
            op = "replace"
            path = "/myJsonPath"
            value = "blah"
        }
    )
}

请求

将TLS设置为1.2,以防万一。

[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12


最后,发送您的请求。成功响应的内容将具有Documents数组属性,您可以从中挖掘。

$response = Invoke-WebRequest -Method $verb -Uri $url -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing


我花了很长时间才弄清楚没有分区键的集合的分区键,所以我想我会在这里记录它。如果你需要更多帮助,或者想挖掘更多,请查看这里:
https://learn.microsoft.com/en-us/rest/api/cosmos-db/documents

相关问题