Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@nijinagome

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

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に変換する方法

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
nijinagome
PowerShellであれこれやることを学んでいます。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?