LoginSignup
2
0

More than 3 years have passed since last update.

PowerShellでElasticsearch検索する(Invoke-RestMethod)

Posted at

PowerShellでElasticsearch検索する

Elasticsearchに投入したデータをなんやかや検索したり集計したりする場合の基本的なところ。
今回は検索のみで集計(aggregations)の話は無し。

前提

本記事はlocalhostのつもりで書く。外部から投げる場合は、投げつけ先のElasticsearchが外部からの問合せに対応していること。yml書いたりFirewall開けたり。X-Pack等でセキュリティ設定している場合はそれに合わせて。

curlとInvoke-RestMethod

JSONを投げてJSONを返してもらうのがElasticsearchの基本。
こういう操作で使うのは、Linuxならおなじみcurl
PowerShellではInvoke-RestMethodコマンドレットを使う。

似たコマンドレットInvoke-WebRequestのことを「PowerShell版curlです」と説明してる例をしばしば目にするが、実際に使ってみると全然違う。エイリアスになってるのが邪魔なくらい。
curl・wgetとInvoke-RestMethod・Invoke-WebRequestは全く異なるものとして新たに覚えるほうが、変な思い込みが元のトラブルを避けられて良い。

curl, wget そしてInvoke-WebRequestの違い

実際の検索

JSON

json.json
{
  "size": 3,
  "query": {
    "bool": {
      "must": [
        {"range": {"requestedAt": {"to": "now-1d/d","from": "now-1d/d"}}},
        {"range": {"queryTime": {"gte": 5000}}}
      ]
    }
  },
  "_source": ["queryTime","requestedAt","searchWord"],
  "sort": [{"queryTime": {"order": "desc"}}]
}

対象は検索ログ。クエリタイム遅かったものを探したい。
昨日一日の検索ログから、クエリタイム5000ms以上かかったものを検索。
クエリタイム・リクエスト時刻・サーチワードを選択。
結果はクエリタイム遅い順3件表示。

なおタイムゾーン指定は省略している。Elasticsearchの格納データは基本UTCなので、日本時間と+09:00ずれる。問題になる場合は自分で操作すること。(そんなことはアプリケーション側でやれというのがElasticsearchの言い分のようだ)

PowerShell版

Post_Search.ps1
# Elasticsearchに問い合わせ
$QueryParam = @{
  ContentType = "application/json"
  Method      = "Post"
  uri         = "http://localhost:9200/search_log/_search/"
  InFile      = ".\json.json"
}
$resp = Invoke-RestMethod @QueryParam

# 結果をコンソールに表示
$resp | ConvertTo-Json -Depth 4

# ファイル出力する
$resp | ConvertTo-Json -Depth 4 | Out-File -LiteralPath .\output.txt -Encoding default

現verのElasticsearchではContentType指定が必須なので必ず書く。
別ファイルから読み込むときはInFileパラメータ、ベタ貼りやGet-Contentで読み込むときはBodyパラメータ。この程度のJSONならベタ貼りでもいいけど、今回はこの後のcurl.exe版比較のため書き方を合わせて別ファイルにした。

取得結果は変数に格納しておくと後であれやこれやするのが楽。
PowerShellらしくSelect-Object | Format-*で表示したり、ConvertTo-JSONで丸ごと表示したり、組み立ててOut-FileExport-Csvでファイル出力したり。

単に表示だけでよくて、ワンライナーなら↓こんなの。

Invoke-RestMethod -ContentType "application/json" -Method "Post" -uri "http://localhost:9200/search_log/_search/" -InFile ".\json.json" | ConvertTo-Json -Depth 4

curl版

Windows版curl.exeを使うならこんな↓感じ。
別途インストールするものがある他、Windows10 ver1803以降には標準で入っているらしい。→Windows10にcurlあるじゃん!という話

curl -H "Content-Type: application/json" -XPOST "localhost:9200/search_log/_search?pretty" -d @json.json

ちなみにJSONを別ファイルにせずワンライナーで書こうとすると、エスケープ無限地獄に落ちるのでよそう。

\{\"range\":\{\"queryTime\":\{\"gte\":5000\}\}\} # ~以下略

か、書きたくない~。

Invoke-RestMethodとcurl.exeどちらを使うか

Windows系なら、どうしてもcurl.exeでなければならない理由があるのでなければInvoke-RestMethodのほうが便利、なはず。
なんたってオブジェクトの形で返ってくるので、後からいくらでも操作し放題だから。curl.exeだと文字列で帰ってくるので、後でJSON読み込んで操作できる何かに渡さないとならない。だったら最初からPowerShell使えばいいよね。(自力で文字列切り張りなんていう非人道的行為は止そう)

応用

問合せのJSONは、連想配列で作ってConvertTo-JSONで変換する方法もあり。どっかからパラメータ貰ってきてJSONにして検索とか。JSONを文字列で組み立てるよりはるかに健康的だと思う。
ハッシュからJSON,JSONからPSCustomObjectに変換する方法

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0