UiPath Data Serviceのレコードを一括取得＆登録する

# はじめに

本記事ではData Service APIを利用し、Data Serviceの任意のエンティティに登録されているレコードを一括で取得し、また取得したレコードを他のエンティティに登録する例をご紹介いたします。
以下のようなユースケースを想定しています。

- テナントAのあるエンティティからテナントBのエンティティにレコードをコピーしたい
- 組織Cのあるエンティティから組織Dのあるエンティティにレコードをコピーしたい

UiPath Studio、Studio WebでもData Serviceのレコードを操作する専用アクティビティが用意されていますが、ここではより汎用的にレコード操作を行う方法として、Data Service APIとPowershellを使用した方法をご紹介いたします。

# UiPath Data Serviceとは

以下の記事にUiPath Data Serviceに関する詳細の情報が記載されていますので、よろしければご参照ください。

https://qiita.com/Kajiita/items/73c066056a17c774ffd4

# 事前準備

PowerShell から UiPath Data Service のリソースにアクセスするには、UiPath Automation Cloud の外部アプリケーション機能を利用して認証情報を発行し、クライアント資格情報フローでアクセストークンを取得します。Data Service の API を利用するために必要なアクセストークンを取得するには、「きめ細かいアクセス権管理」による権限付与が必要です。詳しくは、以下の記事をご参照ください。

https://qiita.com/mstgsg/items/89fe27545b5ee353dca9


# 一括取得

## Queryについて

専用アクティビティの[エンティティレコードにクエリを実行](https://docs.uipath.com/ja/activities/other/latest/workflow/query-entity-records)が利用しているエンドポイント ```https://cloud.uipath.com/{OrganizationName}/{TenantName}/dataservice_/api/EntityService/{EntityName}/query``` にPOSTリクエストを送信してレコードを取得します。
Data Service API では、一度のリクエストで扱えるレコード数の上限が 1,000 件です。そのため、格納されているレコードが 1,000 件を超える場合、```Start``` と ```Limit``` を調整してページネーションを行う必要があります。

:::note
REST APIにおけるページネーション (Pagination) とは、サーバー側が持つ大量のデータを、一度にすべて返すのではなく、複数回に分けて取得できるようにする仕組みです。たとえば、大量データによるレスポンスサイズの肥大化や処理負荷を防止するために利用されます。ページネーションを実装すると、クライアントは必要なページ（あるいは区切り）ごとにリソースを取得できるようになります。
:::


## 実装例

PowerShellによる実装例を以下に示します。下記のパラメータに指定している鉤括弧```{}```で囲われた部分を、ご利用の環境と外部アプリケーションの値に合わせて適宜ご変更ください。
下記のスクリプトの実行に成功すると、同じフォルダ配下に```{エンティティ名}.json```の名称でJSONファイルを出力します。

:::note info
対象とするエンティティ名は```Display Name```ではなく、```Name```である点にご留意ください。
:::

``` query.ps1
param (
    [string] $automationCloudUrl = "https://cloud.uipath.com",
    [string] $organizationId     = "{OrganizationName}",
    [string] $tenantName         = "{TenantName}",
    [string] $cliendId           = "{ApplicationID}",
    [string] $clientSecret       = "{ApplicationSecret}",
    [string] $scopes             = "DataService.Default",
    [string] $entity             = "{EntityName}"
)

#------------------------------------------------
# 1. アクセストークン取得関数
#------------------------------------------------
function Get-BearerToken {
    $Body = @{
        "client_id"     = $cliendId
        "client_secret" = $clientSecret
        "scope"         = $scopes
        "grant_type"    = "client_credentials"
    }
    $tokenEndpoint = "$automationCloudUrl/identity_/connect/token"
    $response = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Body $Body -ContentType "application/x-www-form-urlencoded"
    return $response.access_token
}

#------------------------------------------------
# 2. Data Service のクエリ関数
#    ページネーション付きで最大件数を取得
#------------------------------------------------
function Invoke-DataServiceQueryRecordsAPI {
    param (
        [string] $bearerToken,
        [int]    $limit = 1000
    )

    $headers = @{
        "Authorization" = "Bearer $bearerToken"
        "Content-Type"  = "application/json"
    }

    $DSEndpoint = "$automationCloudUrl/$organizationId/$tenantName/dataservice_/api/EntityService/$entity/query"

    $allRecords     = @()
    $start          = 0
    $hasMoreRecords = $true

    while ($hasMoreRecords) {
        $requestBody = @{
            "Start"       = $start
            "Limit"       = $limit
            "SortOptions" = @(
                @{
                    "FieldName"    = "Id"
                    "IsDescending" = $false
                }
            )
        }

        try {
            $jsonBody = $requestBody | ConvertTo-Json -Depth 20
            $response = Invoke-RestMethod -Uri $DSEndpoint -Method POST -Headers $headers -Body $jsonBody

            # 取得したレコードをallRecordsに追加
            $fetchedRecords = $response.value
            $allRecords    += $fetchedRecords

            Write-Host "Number of fetched records:" $allRecords.Count

            if ($fetchedRecords.Count -lt $limit) {
                $hasMoreRecords = $false
            }
            else {
                $start += $limit
            }
        }
        catch {
            Write-Error "An error occurred while fetching data: $_"
            break
        }
    }
    return $allRecords
}

#------------------------------------------------
# 3. メイン処理
#------------------------------------------------
$bearerToken = Get-BearerToken
$dsResult    = Invoke-DataServiceQueryRecordsAPI -bearerToken $bearerToken

# 結果をファイル出力
$dsResult | ConvertTo-Json -Depth 20 | Out-File -FilePath "$entity.json" -Encoding utf8
Write-Output "Data successfully saved to $entity.json"
```


# 一括登録

## Insert-batchについて

レコードの一括登録処理のため、専用アクティビティの[複数のエンティティレコードを作成](https://docs.uipath.com/ja/activities/other/latest/workflow/create-multiple-entity-records)が利用しているエンドポイント```https://cloud.uipath.com/{OrganizationName}/{TenantName}/dataservice_/api/EntityService/{EntityName}/insert-batch``` にPOSTリクエストを送信します。設定しているパラメータは当該アクティビティの既定の設定と同様とします。
Queryの場合と同様、一度のリクエストで扱えるレコード数の上限が 1,000 件です。したがって、格納されているレコードが 1,000 件を超える場合、1,000 件単位での繰り返し処理が必要になります。

## 実装例

PowerShellによる実装例を以下に示します。下記のパラメータに指定している鉤括弧```{}```で囲われた部分を、ご利用の環境と外部アプリケーションの値に合わせて適宜ご変更ください。前提条件として、同じフォルダ配下にレコードの情報を格納したJSONファイルが```{操作対象となるエンティティ名}.json```の名称で配置されていることを想定しています。

``` insert-batch.ps1
param (
    [string] $automationCloudUrl = "https://cloud.uipath.com",
    [string] $organizationId     = "{OrganizationName}",
    [string] $tenantName         = "{TenantName}",
    [string] $cliendId           = "{ApplicationID}",
    [string] $clientSecret       = "{ApplicationSecret}",
    [string] $scopes             = "DataService.Default",
    [string] $entity             = "{EntityName}"
)

#------------------------------------------------
# 1. アクセストークン取得
#------------------------------------------------
function Get-BearerToken {
    $Body = @{
        "client_id"     = $cliendId
        "client_secret" = $clientSecret
        "scope"         = $scopes
        "grant_type"    = "client_credentials"
    }

    $tokenEndpoint = "$automationCloudUrl/identity_/connect/token"
    $response = Invoke-RestMethod `
        -Uri $tokenEndpoint `
        -Method Post `
        -Body $Body `
        -ContentType "application/x-www-form-urlencoded"

    return $response.access_token
}

#------------------------------------------------
# 2. データをバッチ登録する関数
#------------------------------------------------
function Invoke-DataServiceInsertBatchAPI {
    param (
        [string] $bearerToken,
        [int]    $batchSize = 1000
    )

    $DSEndpoint = "$automationCloudUrl/$organizationId/$tenantName/dataservice_/api/EntityService/$entity/insert-batch?expansionlevel=2&failOnFirst=False"

    $headers = @{
        "Authorization" = "Bearer $bearerToken"
        "Content-Type"  = "application/json"
    }

    # JSONファイルからレコードを読み込む
    $allRecords = Get-Content -Path "$($entity).json" -Raw | ConvertFrom-Json
    if (-not $allRecords) {
        Write-Host "No records found in the JSON file. Exiting..."
        return
    }

    Write-Host "Loaded $($allRecords.Count) records from the JSON file."

    $totalCount   = $allRecords.Count
    $currentIndex = 0
    $pageNumber   = 1

    while ($currentIndex -lt $totalCount) {
        $endIndex     = [Math]::Min($currentIndex + $batchSize - 1, $totalCount - 1)
        $currentBatch = $allRecords[$currentIndex..$endIndex]

        Write-Host "Processing batch $pageNumber : Records $($currentIndex + 1) to $($endIndex + 1) (Total: $($currentBatch.Count))"

        Invoke-RestMethod `
            -Uri $DSEndpoint `
            -Method POST `
            -Headers $headers `
            -Body ($currentBatch | ConvertTo-Json -Depth 20)

        $currentIndex = $endIndex + 1
        $pageNumber++
    }
}

#------------------------------------------------
# 3. メイン処理
#------------------------------------------------
$bearerToken = Get-BearerToken
Invoke-DataServiceInsertBatchAPI -bearerToken $bearerToken
Write-Output "Data successfully uploaded to $entity."
```






# 免責事項

- ここでご紹介するサンプルスクリプトはChatGPT等を利用して自動生成されたものをベースにしております。あくまで動作確認用として提示おり、本番環境での動作を保証するものではありません
- 本記事は2025年3月時点での情報を掲載しております
- ここではTextタイプのフィールドのみで動作検証を行っております。他のデータ型のフィールドについては検証しておりません
- 本記事で記載しているPowershellスクリプトの構文に関するサポート等は受け付けていないため、ご不明点等ございましたらPowershellのガイドをご参照ください



# 参考リンク

https://www.uipath.com/ja/product/no-code-data-modeling


https://docs.uipath.com/ja/automation-cloud/automation-cloud/latest/api-guide/accessing-uipath-resources-using-external-applications#using-the-different-grant-types

# おわりに

本記事では、UiPath Data Serviceのレコード一括操作に関するPowerShellのサンプルスクリプトをご紹介しました。レコード管理の一助になれば幸いです。

それでは快適なUiPathライフをお過ごしください。