PlagueHO / CosmosDB

PowerShell Module for working with Azure Cosmos DB databases, collections, documents, attachments, offers, users, permissions, triggers, stored procedures and user defined functions.
http://dscottraynsford.com
MIT License
152 stars 46 forks source link

Add Update-CosmosDbDocument and Get-AllCosmosDbDocuments #470

Open bcrouzille opened 1 year ago

bcrouzille commented 1 year ago

Feature

Hello,

First of all thank you for this usefull module !!! It would be great to add these two functionalities :

This one let us to send a partial update for a document with a PATCH operation, the json input must be like this :

$operations = @{operations = [System.Collections.ArrayList]@() }
        $update = [PSCustomObject]@{
            op    = "replace" (there are more possible operations )
            path  = "/parent/$index/child"
            value = @($values)
        };

And check that the number of operations is -le 10 (cosmos limite for a simple document update)

function Update-CosmosDbDocument {

    [CmdletBinding(DefaultParameterSetName = 'Context')]
    [OutputType([Object])]
    param
    (
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'Context')]
        [ValidateNotNullOrEmpty()]
        [CosmosDb.Context]
        $Context,

        [Parameter(Mandatory = $true, ParameterSetName = 'Account')]
        [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })]
        [System.String]
        $Account,

        [Parameter()]
        [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })]
        [System.String]
        $Database,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]
        $Key,

        [Parameter(ParameterSetName = 'Account')]
        [ValidateSet('master', 'resource')]
        [System.String]
        $KeyType = 'master',

        [Parameter(Mandatory = $true)]
        [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })]
        [System.String]
        $CollectionId,

        [Parameter(Mandatory = $true)]
        [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ })]
        [System.String]
        $Id,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $DocumentBody,

        [Parameter()]
        [ValidateSet('Include', 'Exclude')]
        [System.String]
        $IndexingDirective,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Object[]]
        $PartitionKey,

        [Alias('IfMatch')]
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $ETag,

        [Parameter()]
        [ValidateSet('Default', 'UTF-8')]
        [System.String]
        $Encoding = 'Default',

        [Parameter()]
        [switch]
        $ReturnJson
    )

    $null = $PSBoundParameters.Remove('CollectionId')
    $null = $PSBoundParameters.Remove('Id')
    $null = $PSBoundParameters.Remove('DocumentBody')
    $null = $PSBoundParameters.Remove('ReturnJson')

    $resourcePath = ('colls/{0}/docs/{1}' -f $CollectionId, $Id)

    $headers = @{}

    if ($PSBoundParameters.ContainsKey('IndexingDirective')) {
        $headers += @{
            'x-ms-indexing-directive' = $IndexingDirective
        }
        $null = $PSBoundParameters.Remove('IndexingDirective')
    }

    if ($PSBoundParameters.ContainsKey('PartitionKey')) {
        $headers += @{
            'x-ms-documentdb-partitionkey' = Format-CosmosDbDocumentPartitionKey -PartitionKey $PartitionKey
        }
        $null = $PSBoundParameters.Remove('PartitionKey')
    }

    if ($PSBoundParameters.ContainsKey('ETag')) {
        $headers += @{
            'If-Match' = $Etag
        }
        $null = $PSBoundParameters.Remove('ETag')
    }

    $result = Invoke-CosmosDbRequest @PSBoundParameters `
        -Method 'Patch' `
        -ResourceType 'docs' `
        -ResourcePath $resourcePath `
        -Body $DocumentBody `
        -Headers $headers

    if ($ReturnJson.IsPresent) {
        return $result.Content
    }
    else {
        try {
            $document = ConvertFrom-Json -InputObject $result.Content
        }
        catch {
            New-CosmosDbInvalidOperationException -Message ($LocalizedData.ErrorConvertingDocumentJsonToObject)
        }

        if ($document) {
            return (Set-CosmosDbDocumentType -Document $document)
        }
    }
}

And this one return ALL the document, I found that the "standard" Get-CosmosDbDocument doesn't return all results :

function Get-AllCosmosDbDocuments {
    [CmdletBinding()]
    param(
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'Context')]
        [ValidateNotNullOrEmpty()]
        [CosmosDb.Context]
        $cosmosDbContext,
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })]
        [System.String]
        $container,
        [Parameter()]
        $query
    )
    $totalDocs = @()
    $ResponseHeader = $null
    $docs = Get-CosmosDbDocument -Context $cosmosDbContext -CollectionId $container -MaxItemCount 1000  -Query $query -QueryEnableCrossPartition $true -ResponseHeader ([ref] $ResponseHeader)
    $continuationToken = Get-CosmosDbContinuationToken -ResponseHeader $ResponseHeader
    $totalDocs += $docs
    while ($continuationToken) {
        $docs = Get-CosmosDbDocument -Context $cosmosDbContext -CollectionId $container -MaxItemCount 1000  -Query $query -QueryEnableCrossPartition $true -ResponseHeader ([ref] $ResponseHeader) -ContinuationToken $continuationToken
        $totalDocs += $docs
        $continuationToken = Get-CosmosDbContinuationToken -ResponseHeader $ResponseHeader
    }
    return $totalDocs
}

I don't have any time to make it by myself so if someone want to do it ... This code is working I use it on my project but make the entire implentation in the module is too long for me at this moment.

Thanks

Ben