im@sparqlを触ってみる その2 - PowerShellのデータ取得を関数化する

imihito.hatenablog.jp

上記の記事でPowerShellから情報を取得することには成功したが、そのままでは使いにくいため、関数に切り出してみた。

動作環境

Windows10 Pro 64bit上のWindows PowerShellのみで確認。

> $PSVersionTable

Name                           Value                                                  
----                           -----                                                  
PSVersion                      5.1.17134.165
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17134.165
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

コード(psm1)

毎回クエリを投げるのは負荷的に避けたかったため、簡単なキャッシュ機構を付けてみた。

ただ、関数だけでは状態を保持しにくいため、モジュール(psm1)として、モジュール内の変数にキャッシュを保持させる構成としている。

# 結果のキャッシュ
[Collections.Generic.Dictionary[string,psobject[]]]$jsonCache =
    New-Object -TypeName 'Collections.Generic.Dictionary[string,psobject[]]'

function Request-Imasparql {
    [CmdletBinding()]Param (
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$QueryString
    )
    Set-StrictMode -Version Latest
    $ErrorActionPreference = 'Stop'

    # 改行及びインデント削除
    [string]$trimQuery = 
        [regex]::Replace( $QueryString , ' *[\r\n]{1,2} *' , [string]::Empty )

    # キャッシュにあれば情報取得&リターン
    [psobject[]]$jsons = @()
    if ( $jsonCache.TryGetValue( $trimQuery , [ref]$jsons ) ) {
        Write-Information 'use cache'
        Write-Information ('query = ' + $trimQuery)
        return $jsons
    }
    
    
    Write-Information 'access'
    [Net.WebClient]$wc = 
        New-Object -TypeName Net.WebClient -Property @{
            BaseAddress = 'https://sparql.crssnky.xyz/spql/imas/query'
            Encoding    = [Text.UTF8Encoding]$false
        }

    # クエリの設定
    $wc.QueryString.Set( 'output', 'json' ) # 出力形式
    [string]$escapedQuery = [uri]::EscapeDataString( $trimQuery )
    $wc.QueryString.Set( 'query', $escapedQuery )
    Write-Information ('escaped query = ' + $escapedQuery)

    [string]$jsonTxt = $wc.DownloadString( [string]::Empty )

    [psobject]$data = ConvertFrom-Json -InputObject $jsonTxt
    $jsons = $data.results.bindings
    $jsonCache.Add( $trimQuery , $jsons )
    
    return $jsons
}

Export-ModuleMember -Function Request-Imasparql

サンプル

上記モジュールを使って前回の記事と同じ処理を書くと以下のようになる。

Import-Module -Name '上記コードを○○.psm1として保存して、保存したファイルのフルパス'

# https://sparql.crssnky.xyz/imas/ 内の「千早のセリフテキストを取得」のクエリ
[string]$query = @'
PREFIX schema: <http://schema.org/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX imas: <https://sparql.crssnky.xyz/imasrdf/URIs/imas-schema.ttl#>

SELECT *
WHERE {
  ?s rdf:type imas:ScriptText;
     imas:Source ?source;
     schema:text ?text.
  ?source schema:name ?name;
     filter(regex(str(?name),"千早"))
}order by ?text
'@

# 情報取得
[psobject[]]$resultJson = 
    Request-Imasparql -QueryString $query -InformationAction Continue

# 必要な情報をコンソール出力
$resultJson | 
    select -Property @(
        @{N="Name";E={$_.name.value}}, 
        @{N="Text";E={$_.text.value}}
    ) |
    Write-Output