はてだBlog(仮称)

私的なブログど真ん中のつもりでしたが、気づけばWebサイト系のアプリケーション開発周りで感じたこと寄りの自分メモなどをつれづれ述べています。2020年6月現在、Elasticsearch、pandas、CMSなどに関する話題が多めです。...ですが、だんだんとより私的なプログラムのスニペット置き場になりつつあります。ブログで述べている内容は所属組織で販売している製品などに関するものではなく、また所属する組織の見解を代表するものではありません。

Elasticsearch percolator再び

Elasticsearch percolatorと私

再びとはなんぞやといいますところ、このブログの中での登場が2回目ですという意味です(笑)。

最初の登場は、こちら。

itdepends.hateblo.jp

上記の説明では、percolatorについては、公式リファレンスの直訳・意訳で検索条件をインデックスに入れて...のようにまとめました。

が、

Elasticsearch percolatorの便利さは上記では説明できていない

今思えば、percolatorが何に向いているか・何ができそうかを中心に説明しても良い気分です。

ググったところ、percolatorの仕組みを先に説明されている例が多いため、ここでは多少外れていても、仕組みは後回しにどちらかと言えばpercolatorの良さをアピールするような説明をすると、だれかの役に立つのではと思ってこちらに書き綴って見ます。

とまあ、もったいつけていいますが、

Elasticsearchのpercolatorは、

Elasticsearchの構成を活かした、後述するある仕掛けにしたがうことで、

他の手法より簡単に

あるドキュメント(JSON形式で表せるあるドメインのオブジェクト)が、 特定の条件に収まっているか/外れているかを

判定できる仕組みです。

なんか普通ですか? 

ちょっとアピール不足かな。

すみません> Elasticsearchちゃん。

ちなみに、ググった範囲ですが、下記を見る限り、同じluceneファミリーのsolrには、percolatorに相当するものは無いようですね。

stackoverflow.com

percolatorは判定エンジン(仮称)

さて、ドキュメントが...判定できるというのは、つまるところ、次のようなことができます。

  1. カテゴリの分類
  2. なんらかの条件の範囲内であること
  3. なんらかの条件の範囲外であること
  4. ビジネスルールのバリデーション

などなどです。

上記の例全般はもちろん、その中でもエッジケースぽくてかつアプリでロジックを組みたく無いなー的なものにも相性が良いです。

例えば、ドキュメント中にNGワード(チェック対象のワードはそれなりのワード数)が入っていないかのチェック(あるいは入っているのチェック)とか、判定条件自体が形は似ているけど都度になるので判定条件自体をあらかじめ別の場所で生成しておきそれとぶつけたい*1というようなものがあげられます。

これは後述のとおり、通常はプログラムのメインのロジックで、ある条件1に該当するか、条件2に該当するか... というような対象の条件全てを適用してチェックするのと異なり、percolatorでは、あらかじめ定義した条件のうち、マッチするものがあるかという依存関係の逆転(dependency inversion principle) ぽい方式になることも貢献していると思います。

percolatorの判定ロジックはElasticsearchの検索クエリDSLで設定できる

Elasticsearchの構成を活かした、後述するある仕掛け...はさらに後述するとして、これらの判定条件は、ElasticsearchのクエリDSLが利用できます。

よって、(JOINや相関問い合わせを伴わない)SQLのWHERE句でいけるようなことはひととおりできますし、Elasticsearchの全文検索エンジンならではの次のような条件を使うこともできます。

つまるところ、プログラミング言語でif文やelse文を組み合わせてでごちゃごちゃしたり、ごちゃごちゃを回避しようとして潔癖に無理に継承などで集約してかえってわかりにくくなってしまうようなところを、判定用の式を組み合わせて宣言的に(贅肉を落として)構成できる&あえて外出しできるというところが、他の手法に対して一つのアドバンテージになっています。

  1. 全文検索のmatch句を使った条件判定
  2. Geo系のクエリの利用
  3. Range系のクエリの利用
  4. 検索対象フィールドのワイルドカード指定などのシンタックスシュガー
  5. (ちょっと飛躍するかもしれませんが)前項のシンタックスシュガーが用意されていることと全体的に「式」からなる宣言的な記法のため、コード値などをハードコーディングしても可読性やメンテナンス性が落ちにくい。(ここでは、原理主義的な外部定義よりは、適度なハードコーディングはビジネスロジックを直接表現しているのでわかりやすい場合もあるという立場で述べています。)
  6. Geo系のポリゴン当て、Rage系のINTERSECTS、(試していないですが)Span queriesのような、JSONならではの構造化データに対する複数次元の範囲でヒットさせるような方法*2

2019/2/12 23:00 追記 上記で、いろいろできるとぶっ放していますが、実は使えるクエリDSLの組み合わせに制限があるような気もしてきました。このような記事を書いておいて調査が甘くて申し訳ありませんが、実際の使用はmapping設定に留意の上、お手元の環境で実際にお試しください。

参考: www.elastic.co

判定ロジックをストックできる

もう一つの便利なところは、Elasticsearchの構成を活かして、この判定条件をインデックスに文字通りストックしていくようなことができます。

図で示すとこんな感じです。ここまで引っ張った「Esの構成を活かした...後述」も盛り込んだつもり。

f:id:azotar:20190211232556p:plain

頑張ってまとめてみましたが伝わるかな〜? 

余計わかりにくくなっているかもしれないと不安になりつつ、実際にpercolatorを試してみれば、腑に落ちる点もあると思いますが...

www.elastic.co

判定エンジンらしくAPIとして使うことができる(と思う)

さて、検索の世界から少し逸脱しますが、このような判定の仕組み&判定条件をストックしていけるというのは、アプリケーションの世界での更新系やデータ管理の基礎機能での使い勝手が良いです。

私見ですが*3、この判定条件をアプリの本体ロジックとは少し切り離して一見無関係なElasticsearchにストックしていける(HTTPのAPIとしても使える)ので、これを緊急回避的に設定可能なライブラリとして追い出す選択肢があると、設計のアソビをもうけやすくなります。

というのも、例えば、DDDなどにおいては、ビジネスルールだビジネスロジックだ、あるいは安定していると言われている「データ」に関するバリデーションのロジックについては、各所で知見がまとめられているように、ドメイン知識として濃淡や変化するものしにくいものの仕分けして適当な責務のクラス設計などに振り分けてことになるというのが定石だと思いますが、実のところ特定分野ではこのドメイン知識の密度の見極めが難しく、プログラムの設計としてはベストというものが実現できたとしても、それでもドメイン知識の重要なものとそうでないものを見誤って、それほど重視しなくて良いところを手厚く、またその逆になってしまうこともしばしばあります。

まあ、そんなことができるだけ少なくなるように、モデリングの工夫やうまい手法をみなさんが研究されているのだと思いますが、やはり当初はそれが「安定した論理=コアのドメイン知識」として見えやすい(そしてその当初の時点ではその見立ては間違っていない)のがやっかいで、コアだと思ってがっつり実装したらそうでもなかったということもよくある話だと思います。

ということで、そんな設計に迷うような場合に、PoCや初期時点では、ビジネルルールレベルのバリデーションなどをElasticsearchのpercolatorに追い出しておくというのは、悪くない案だと考えています。

まとめ

Elasticsearchのpercolatorについて、データ更新の際に便利だぞということで、自分の感じたことを書いてみました。

最後にもういちど検索の話に戻ると、メインの検索の前に、percolatorでなんらかの一次判定をしてやるという用途はもちろん使えます。

また、複雑な検索条件の前借りにも使えます。

何かというと、メインのインデックスにドキュメントをPOSTする前に、percolatorでカテゴリ判定したり、以前の下記の記事で主張させていただいた「ビジネスロジックの圧縮((percolatorは、複数フィールドを持つあるドキュメントに対してその複数フィールドの独特のビジネスロジックをpercolatorの検索で判定してやり、検索サービスに必要な最小限の知識(1フィルードのBoolean)に集約する」という用途でも力を発揮すると思います。

itdepends.hateblo.jp

是非みなさんもうまい使い方を見つけて情報公開いただけると私もマネマネさせていただいたいと思っています。

具体的なデータを使ったプッシュ記事を書きたいけど、今回はひとまずここまで。

ここまで読んでいただきありがとうございました。

*1:例えば、ある地点の座標の緯度経度を情報として持つデータがあって、これがあるあらかじめ定義したエリアの範囲にあるか → https://techlife.cookpad.com/entry/2016/03/17/090000

*2:※ Elasticsearchの検索系のDSLを実際に使ったことがあるひとならなんとなく分かるかもという表現としました。この記事他の説明と比べても、乱暴な用語を用いつつ、しかもそれの説明は割愛しています。ご了承ください。

*3:もちろん、このブログ全般が私見の塊ですが...

Vue.js版ReactiveSearchのお試しコード例の2例目(カスタムクエリ型利用の場合にVuexを使って複数検索BOXまたがりる)- ElasticsearchのPoC

はじめに

itdepends.hateblo.jp

この記事はこちら↑の続きです。

冒頭のリンクのとおり、Elasticsearchをターゲットにした便利なSPAプラグインであるReactiveSearchを使ってみたのですが、ここではReactiveSearchにクエリを任せる標準方式ではなく、カスタムクエリ型で実現しました。

カスタムクエリ型の場合、Vue.js版のチュートリアルを流し読みしたのと私の英語読解力の範囲では、コンポーネントのプロパティ設定レベルでコンポーネント間で検索条件を共有するすることが難しいように見えました。 (ReactiveSearch自体のソースは読んでいない上の見解です。)

例えば、検索クエリはオリジナルなものにしたいが、加えて検索BOXを2つにしてそれぞれ別フィールドを検索する、また検索BOX1つめと2つめのAND(Elasticsearch クエリDSLで言うと、must)で検索したいというようなものをやるにはどうしたらというところです。

f:id:azotar:20190210133336p:plain

とは言え、Vue.jsに載っているアプリですので、このようなことも多少味付けすればできるハズなのは確実なのですが、念のため確かめてみました。

で、結論としては、Vue.jsのコンポーネント間の状態共有を使う方式一般で取り扱えそうです。

今回は、Vue.jsのステータス管理のプラグインであるVuexを付け足して使うことにしました。以下、その簡単な経緯とひとまず手元では動作したというサンプルコードです。

目次

まずは動かす

先に動かしてからの方が話がとおりやすいと思いますので、以下のコピペ手順で動かしてからちょいとだけ補足します。

なお、説明を簡単にするため、冒頭に述べた前回のものが動作している&環境の前提条件が整っているとします。

Vuexをインストール

例えばnpmでインストールしてください。

npm install vuex

Vue CLIでVuexが有効なプロジェクトをcreate

例えば、こんな感じでVue CLIを起動します。

vue create rs-sample-search-vuex

「Manually select features」を選択します。

次にこんな感じの画面が表示されるので、Vuexが対象になるように選択してください。

f:id:azotar:20190210135517p:plain

createしたプロジェクトのディレクトリのmain.js、store.js、App.vueを置き換え

それぞれ次の内容で置き換えて保存してください。

なお、時間があれば、置き換え前に、雛形になっているデフォルトのmain.js stone.jsを見ておくと、Vuexのお作法が見て取れます。(キーワードは、store、state、mutations、actionsあたりでしょうか。)

main.js

ReactiveSearchのお試しコードなので、ReactiveSearchをimportしたり「use」しているのはもちろん、「store」というところに注目ください。

import Vue from 'vue'
import App from './App.vue'
import store from './store'
import ReactiveSearch from "@appbaseio/reactivesearch-vue";

Vue.config.productionTip = false

Vue.use(ReactiveSearch);

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

store.js

検索BOXを2つ設けるとして、それぞれの現在の入力値を保持する(つもり)プロパティ(ここではkwsと名付けました)とそれらを操作するためのメソッドを定義しています。

ちょっとアレなコーディング&実装アーキテクチャかもしれませんが、ここでは、ReactiveSearchとVuexの噛み合わせを示すための例にしてあります*1

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    kws :{
      k1: "",
      k2: ""
    }
  },
  mutations: {
    mut_KW_UPDATE1(state,text){
      state.kws.k1 = text
    },
    mut_KW_UPDATE2(state,text){
      state.kws.k2 = text
    }
  },
  actions: {
    kw_update1(state,kw){
      state.commit("mut_KW_UPDATE1",kw);
    },
    kw_update2(state,kw){
      state.commit("mut_KW_UPDATE2",kw);
    }
  },
  getters:{
    kws(state){
      return state.kws;
    }
  }
})

App.vue

Vuexを使う&ここまでのおまじないで、「単一コンポーネント(App.vue)」の中で、「store」について次のことができるようになります。

  1. 「this.$store.dispatch」で、store.jsで定義されている「更新のためのメソッド」に引数を与えて、「store」のデータを更新できる。
  2. 「this.$store.getters」で、store.jsで定義されている「store」のデータを取得できる。
<template>
  <div id="app">
    <reactive-base app="rs_index" url="http://localhost:9200/" >
    <h5>検索お試しランチャー(Vuex)</h5>

    <data-search
        componentId="myDataSearch"
        placeholder="検索キーワード1"
        @valueChange="sb1ValueUpdate"
        :customQuery="myCustQuery"
        className="data-search"
    />

    <data-search
        componentId="myDataSearch2"
        placeholder="検索キーワード2"
        @valueChange="sb2ValueUpdate"
        :customQuery="myCustQuery"
        className="data-search"
    />
    <result-list
        componentId="mySearchResult"
        :react='{ or: ["myDataSearch","myDataSearch2"]  }'
        :renderData="getResultList"
        :from="0"
        :pages="5"
        :pagination="true"
     />
    </reactive-base>
  </div>
</template>

<script>
export default {
  name: "App",
  methods:{
    sb1ValueUpdate(value){ this.$store.dispatch('kw_update1',value) },
    sb2ValueUpdate(value){ this.$store.dispatch('kw_update2',value) },
    myCustQuery() {
       let kws_words = this.$store.getters.kws.k1 + " " + this.$store.getters.kws.k2 ;
       return { query:{ multi_match: { query: kws_words, fields:["title_ja","content_ja"] }}};
    },
    getResultList( data ) {
        return { title: data.title_ja,description:`<em>${data.title_ja}</em>` };
    }
  }
};
</script>

<style>
.data-search{ width: 800px; }
</style>

アプリを起動してブラウザでアクセス

例えば、次のように起動してください。

npm run start


手順ここまで。

今気づきましたが、ブラウザのコンソールにはワーニングが出まくっています。

また、操作によっては時々不思議な挙動*2をするもののひとまず動いています。

f:id:azotar:20190210135755p:plain

解説(もうちょっとだけ)

上記の単一コンポーネントApp.vueについて補足します。

  1. myCustQueryの返り値のJSONオブジェクトが、Elasticsearchに投げられるクエリDSLになります。ここでは今回の2BOXならではの検索クエリにはなっていませんが、例えば、この例のように、kws_wordsで検索ワードを与えることができていることは見て取れると思います。
  2. そのkws_wordsという文字列の変数は、storeから取得できています。
  3. storeは検索BOXの値を取得しているのですが、sb1ValueUpdate、sb2ValueUpdateという関数でアップデートされる仕組みになっています。
  4. sb1ValueUpdate、sb2ValueUpdateは、ReactiveSearchのdata-searchコンポーネント「@valueChange」でイベント関連付けされています。@valueChangeはそのコンポーネントvalueを指定された関数に引数として渡してくれるものです。要はこの検索BOXでいうと、検索BOXのテキストボックスに入力された値が変更されると、@valueChangeがReactiveSearchの仕組みで呼び出され、さらにsb1ValueUpdate、sb2...の対応するものが起動され、storeに保持される。というものになっています。

前回の例だと、customQueryで指定された関数の第一引数で、検索BOXのテキストボックスの値が受け取れるためこれを検索ワードに使っていましたが、今回は複数の検索BOXの値を使うため、storeを介して2つの検索BOXの値を取得するようにしています。

customQuery、@valueChangeその他についてはこちら↓ opensource.appbase.io ※こちらを見てこの記事で間違っているところがあれば是非是非ご指摘ください。

参考リンク

Vuex公式など

Vuexを特に予告なく登場させましたが、これらの公式についてリンクします。

vuex.vuejs.org

jp.vuejs.org

Vue.js Vuex、その他コーディングスタイルやアーキテクチャについて参考

本記事では記事を単純にするための私の構成力の都合で、いつもどおりアドホックな例に止まっていますが、コンポーネント間の通信についてはいろいろ考えどころがあります。 こちらについて、いくつか参考リンクを貼っておきます。

design.dena.com

medium.com

jp.vuejs.org

基礎から学ぶ Vue.js

*1:下手なコードの言い訳と本来はもう少し検討する必要があると思いますが、ここではそこまで述べていませんという意味です。

*2:不安定というよりは、あるコンポーネントが"こういう"条件の時に"こうなる"というReactiveSearchの仕様だと思いますが...

3分で分かる(ことを目標にした)Adobe XDの使い方速習メモ(邪道編 福笑い手法)

はじめに

本職のデザイナーさんはいるけど、いろいろあってエンジニアとしての自分もAdobe XDをちょっとさわる必要がある、あるいは検索UX担当としてイケてるツールでお絵かきしたい。 (というか、PowerPointや神EXCELは少し休みたい)

... という時に、さくっとAdobe XDが自分と水が合うか確認するという程度に、Adobe XDの操作感を速習するためのメモをまとめてみました。

PowerPointはある程度使える人を前提にしています。ただし、PowerPointに慣れているとそれがアダになる部分もあります。

また、このブログではやんわり検索サイト関連の弱いエンジニアリングを裏テーマとしているので、検索サイトに関わっているとしてという設定で記載しました。 (が、それっぽいことは出てこなくて、後述のUIキットの収集範囲が限られるよねという話。)


mac OS版で説明していますが、Windows版でもそんなに変わらない(レベルの話しかして述べていない)です。 3分で説明するため、正式用語は使っていません。「コレ」とか「ソレ」などを多用しています。

この順で触って見ることで、操作方法のエッセンスがつかめるのでは?、時間がない場合にも付け焼き刃で対応できるのではという例です。

私はデザイナーでも、XDを使いこなしているわけでもないので、本来のXDのパワーを引き出しているわけではありませんので、ご了承ください。

Adobe XD をインストール

Adobe XD をインストールしてください。 <略>

UIキットを入手

公式からUIキットを入手します。

www.adobe.com

Marcelo Silvaさん、Sarah ParmenterさんらのUIキットがダウンロードできますのでダウンロードしてください。

この記事執筆時点では、ダウンロードのリンクは、上記ページの真ん中あたりの「次のステップ」あたりにあります。

また、4つのUIキットがおすすめされていますが、Apple Watch用分も含めて4つをダウンロードをオススメします。

Apple Watch用は、Apple Watchのアプリデザインとしてではなくて、正方形の画像集として使います。

※UIキットと呼ばれていますが、拡張子.xdのファイルなので、ダブルクリックするとXDが起動します。

あと、ワイヤーフレームといえばということで、こちらでしょうか。

blogs.adobe.com

 XDの起動とこの時点でのミニマムな操作ショートカット

ここで、先ほどダウンロードした、UIキットのxdファイルをダブルクリックして起動してみましょう。

ツールバーの解説

f:id:azotar:20190207210131p:plain

(A) デザイン → これをポチるとお絵かきモードです。

  • 0のエリア → 矢印が青くなって選択されていることを確認ください。
  • 1のエリア → お絵かきワークスペースです。
  • 2のエリア → お絵かきワークスペースで選択したオブジェクトの色やフォントのプロパティです。 ただし今回の説明の範囲では使いません。
  • 3のエリア →  選択したオブジェクトの配置や形状などの調整パネルです。

ワークスペースの中の操作ですが、ひとまず次のワークスペースの範囲自体の操作を覚えてください。

操作 mac windows
拡大・縮小 command + マウスホイール ctrl*1 + マウスホイール
ワークスペースの表示枠の移動 スペースバー + マウス操作 未確認ですが、macと同じだと思います。

※オブジェクトの移動はそもそもどうなんじゃいというところですが、ここでは気にしないことにします。

(B) プロトタイプ → これをポチると画面遷移などを仕込むモードです。

プロトタイプモードの時に、オブジェクトをマウスで右クリックすると青い矢印の取手のようなアイコンが出てきます。 こいつをクリックして、リンク先のページやオブジェクトにドラッグしてやると、画面遷移の設定ができます。

f:id:azotar:20190207210216p:plain

(C) 右の方にある再生ボタン

プレビューウィンドウが立ち上がり、プロトタイプの画面遷移などの確認ができます。

福笑い操作の習得

再び、(A)デザインモードに切り替えてください。

気になっているUIオブジェクトをalt(windowsの場合は確認していませんがおそらくctrl)を押しながら、右クリックしてください。

そのまま適当なところに、ドラッグしてください。 → UIオブジェクトがコピーされました。

操作 mac windows
福笑い alt + 右クリックドラッグ ctrl + 右クリックドラッグ ※PowerPointと同じ(?)

f:id:azotar:20190207210301p:plain

アートボード(≒ デバイスのディスプレイ ≒ いわゆる画面)

先に福笑いを説明しましたが、本来は「画面」の下地に配置していくことになります。

先の(A)の0のエリアにある、コレをクリックしてください。

f:id:azotar:20190207210340p:plain

よく見ると、右の方に、iPhone X/XSなどとあるのでターゲットデバイスに該当するものを右クリックしてください。

すると、お絵かきワークスペースの適当な空き地に、白地のアートボードが配置されました。 あとは、0のエリアの矢印アイコンで、操作モードを元に戻し(キーボードだとEscキー)、前項の福笑い操作でぽちぽちUIオブジェクトを配置してみてください。

つまるところ、なんとなく使いそうなかつフリーで配布されているUIキットを集めておいて、あとは、オブジェクトを真面目にイチから作るのではなく配置していくことで、サンプルデザイン&プロトをつくりましょうということになります。


操作説明はここまでです。

マイ作業台のxdファイルを整頓

ダウンロードしたUIキット群からマイフェイバリットを抜き出したUIキットを作っておきましょう。普段は使わなくてもいざという時にパワポ絵よりイケているイメージ絵が短時間で作成できるのカモ。

f:id:azotar:20190207210434p:plain

なにやらサーブリック分析したくなります。

プロトタイプツールとして真面目に使う

HTMLやCSSのエクスポートはできないようですが*2、その分(?)配色などを一括で切り替えたりといったこともできるようです。 ここから先は、動画のチュートリアルを見るのがよさそうです。

www.youtube.com

以上です。ありがとうございました。

*1:ごめんなさい未確認です。PowerPointと同じと想定

*2:できたとしてもトレードオフがあるでしょうから、プロトタイプに特化した方が良いようにも思います。

Vue.js版ReactiveSearchのお試しコード例

Elasticsearchで検索の当たり具合などをいろいろ試すために、アドカレ2018で知ったReactivSearchに目をつけました。 そこで、ReactiveSearchのVue.js版のアドホックなかつできるだけミニマムな動作例の自分用コピペ元が欲しくなりまして、以下に手順的なものをダンプします。 (見てのとおり、全体的に「動けば良い」というスタイルのものなので、その点ご注意ください。)

動かしてみる

Elasticsearchの準備

  1. Elasticsearchに、インデックス(ここでは名前は「rs_index」とします)とデータ(フィールド名はtitle_ja、content_jaとします)を登録。
  2. ElasticsearchをCORS対応で起動(elasticsearch.yml)。→ http://localhost:9200/で起動したとします。

Node.jsをインストール

npmをインストール

ReactiveSearchのVue.js版をインストール

npm でreactivesearch-vueをインストール

npm install @appbaseio/reactivesearch-vue

Vue CLI (Vue.jsのcliコマンドラインインタフェース))をインストール

npm install -g @vue/cli

Vue CLIでプロジェクトを作成

vue create my-awesome-search

ちなみに、my-awesome-searchのところが、このアプリのブラウザでアクセスした際のtitleになります。

検索窓と検索結果の宣言(App.vue)

プロジェクトのディレクトリのsrcに移動して 、App.vueに次をコピペ。奇妙なインデントなのはご容赦。

<!-- App.vue  --> 

<template>
  <div id="app">
    <reactive-base app="rs_index" url="http://localhost:9200/" >
    <h5>検索お試しランチャー</h5>

    <data-search
        componentId="myDataSearch"
        :customQuery="myCustQuery"
        placeholder="検索キーワード"
        :dataField="['title_ja']"
        URLParams="true"
        className="data-search"
    />
    <result-card
        componentId="mySearchResult"
        :react='{ or: ["myDataSearch"]  }'
        :renderData="getResultList"
        :from="0"
        :pages="5"
        :pagination="true"
     />
    </reactive-base>
  </div>
</template>

<script>
export default {
  name: "App",
  methods:{
    getResultList( data ) {
        return { title: data.title_ja.slice(0,5), image:"http://localhost:80/" + `${data._id}.png`, description:`<em>${data.title_ja}</em>` };
    },
      myCustQuery(value) {
          return { query:{ multi_match: { query: `${value}`, fields:["title_ja","content_ja"] }}};
    }
  }
};
</script>

<style>
.data-search{ width: 800px; }
</style>

ラフに起動するだけなら写経のmain.js

main.jsを次でコピペして上書き。

// main.js

import Vue from 'vue'
import App from './App.vue'
import ReactiveSearch from "@appbaseio/reactivesearch-vue";

Vue.use(ReactiveSearch);
Vue.config.productionTip = false

new Vue({
    render: h => h(App),
}).$mount('#app')

アプリをひとまず起動して触ってみる

プロジェクトのsrcディレクトリで次をタイプ。

npm run serve

f:id:azotar:20190204001744p:plain

→ この例だと、http://localhost:8080/にアクセスすると、アプリの画面へ。

f:id:azotar:20190204002241p:plain

※手抜きなので、真っ白です。

アプリが動作するところまでは以上の通り。

補足

前述のApp.vueを手抜き解説します。今回必要になった(?)例に特化したオプション設定と、それに合わせた説明なので、公式が推しているスタンダードかつ便利な使い方と違うところもあります。 興味を持たれた方は、参考文献に示す有識者の方の解説サイトや公式リファレンスを参照ください。

f:id:azotar:20190204004723p:plain

  • result-cardのところは、result-listに変えると検索結果がリスト型になります。
  • 「react」のところは、data-searchなど、"リアクト"させる他のコンポーネントのcomponentIdを指定します。
  • ここでは、「:customQuery」を使って、自前のクエリを定義していますが、実はこちらはオプションで必須ではありません。定義しなければ、「:dataField」に指定のフィールドが検索対象になるようです。また、今回は自前のクエリを使いたかったのでこのようにしたのですが、他のコンポーネントを複数並べてできるだけ手間をかけずにそれでもリッチな検索UIを実現したい場合は、無理に「:customQuery」にしない方が(おそらく)得策です。
  • renderData="getResultList"からの、getResultListで、title、image、descriptionに(特にtitleは5桁でチョップ)妙な値を渡しているのは、title、image、descriptionはコンポーネントの約束事として、渡す値はJavaScript、Vue.jsの世界の範囲ならOKだよねという確認がしたくての、例のための例です。

参考文献など

ReactiveSearch Vue.js版の公式

opensource.appbase.io

↓こちらを先に読んだ方がわかりやすいかも。 opensource.appbase.io

Reactivesearchでいい感じの検索SPAを30分ぐらいで作る(j-yamaさん)

qiita.com

私のこの記事では結果オンリーのオレオレ説明となっていますが、↑こちらのブログでは非常に丁寧な説明がされています。 Vue.jsじゃなくてReact.jsだという人はもちろん、仕掛けや仕組みを抑えたい場合は、私のこの記事よりもこちらのブログを参照ください。私は公式のVue.js版のリファレンスよりもj-yamaさんのReact.jsのコード例を見て、上の方に貼り付けたApp.vueの動作確認コードを作成しました!!

とあるタイプの検索サイトのElasticsearchを使ったサービス設計などに関する私見(2019年改訂版)

検索サイトで、どのようにElasticsearchを活かしてサイトをディレクションするかについて自分の意見をまとめてみました。

まとめてみたと言いいつつ、アタマの整理の過程をダンプしたという体裁になっています。... のでまとまってないかもしれません。

何かの勢いで書いてはならないことを書いてしまわないようにしたため、筆者のドキュメント力とは別の問題として、本来は具体的なもので述べるところ、抽象的な言い方になっているところが多々あります。

一方で、多少リアルな例にしたいと思い、ある程度シーンを絞って記述したところもあるのですが、抽象化との兼ね合いで、論理の飛躍や検証が甘いところもあると思います。

つまるところポエムになっているかもしれません。

また、2019年改訂版としていますが、改訂前のものがあるわけではありません。今後、世の進歩とともに、陳腐化するかもという言い訳でして、2019年現在のこういうスタイルもある...という意味です。

TOC

この記事で想定する検索サイトユースケース

検索を伴うサイトと言いましてもいろいろありますが、次の表の分類4、5あたりをうっすら想定してまとめています。

f:id:azotar:20190123220411p:plain

説明の都合、本来は同時にあり得ない、求人検索サイト、レストラン検索サイト、ECの商品検索サイトの検索要件で求められそうな要素(例. 検索BOXは募集職種とエリアの2BOX系。原本データは基幹システムなど上流システムで管理されている。... など)を混在で気まぐれで引用して説明を試みています。

なお、クチコミなどUGC由来のテキストデータも検索対象としてイメージしていますが、UGC自体がドキュメントの最重要コンテンツとなるような検索サイトではないこととします。これは、このようなUGCの検索サイトにおいて本記事の内容が無意味というものではないと思いますが、UGCメインのサイトの場合は、コミュニティ運営あってこそで、そこを含めて論じないと話が繋がらないためです。

とある検索サイトの悩み

なお、分類4などは他の例と別の悩みを伴うことが多いのではと思います。 (これがこの記事を書いた背景です。)

コンテンツデータが増えてきて、カテゴリ目次だけのディレクトリ型では立ち行かなくなったので検索エンジンを入れようという話になりました。

一方で、一見さんの多い(かもしれないサイト)としては、どんな検索ワードが使われるか予想がつきません。

データ件数は多少揃ってきているものの、当初のディレクトリ型の目次のワードが正しくアタマに入っていて、これらのワードを検索語として検索してくれる人がどれほどいるでしょうか。

precisionとrecall、F値の世界とは別の世界が広がります。

結構データ件数があり本当はエンドユーザーの期待にそえる(かもしれない)データはそれなりのはずだが、実際は検索結果が0件になってしまう。

ということで、ローンチやリニューアル後の検索結果の0件分析は必須だとして、そうは言ってもリニューアル前に逃した魚が大きい...とならないようにせっせと工夫をすることになると思います。

同じ「検索」でも実は結構違う

f:id:azotar:20190125003816p:plain

検索語の派生について

本来は、チューニングと言えばF値という話になるのでしょうが、思いの他、ユーザーはドキュメントに合わせた検索ワードで検索してくれませんし、検索結果の最初の数件しか見ない傾向がより強いように思います。

ドメインが限られた世界では、多少幅を持たせてヒットさせてやる方が重要なんだと思います。

どっちかと言えば、再現率重視ということになるのかもしれません。 まちがっているかもしれないけど、本当はこの辺を探してたんでしょ?というところを端っこにでもhitさせてやるような方向だと思います。

Elasticsearchなど昨今の検索エンジンの機能や仕組みに乗っかると以前はできなかったようなことが平易になります。よって、これらを活用した場合、例えば次のような戦略です。

  1. 形態素解析n-gramのハイブリッド。→ 漏れの防止。一方、前者の加点を高めとすることで、適合度が高そうなものの優先確保。
  2. エリア条件など、厳密な語が入力された方が確実なヒットにつながりやすく、かつある程度エンドユーザーも知識があるような検索条件の入力BOXについては、オートコンプリートを(他の案件より優先して)設置。
  3. ユーザーの入力した語から検索語を派生させて、それらでOR検索する。派生させる語はできれば実際にドキュメント中に現れる語にするのが良いでしょう。
  4. 検索語を派生させてOR検索すると当たり幅が広がります。加えて、複数フィールドを串刺しで検索するとなおさらです。幸い、今回例にしているような検索サイトの例でいうと、複数のフィールドの中にも、ここに検索語が入っていれば優先したいというフィールドがそれなりに存在します。レストラン検索で言えば店舗名、求人募集検索で言えば企業名といったユニークになるフィールドです。また、同じ観点の次点の例としては、すごく当たり前のことを言いますが、レストラン検索のジャンルや求人募集検索の職種や資格のフィールドも視野に入ります。 

ここで言う、検索語の派生は次の図のような塩梅です。

なお、複数ワード入れられた場合はどう考えるのが良いでしょうか。次の図では複数ワードの場合も織り交ぜて私見を述べています。

f:id:azotar:20190123225928p:plain

ユーザー入力の個々のワードはOR検索用に派生させつつ、複数の入力ワード間は世の感覚に合わせてANDにする、というやり方の場合少し工夫が必要かもしれません。 (Elasticsearchのmatch系は入力ワードに対してデフォルトでOR検索です。ここで主張しているように派生させつつ、元の複数の入力ワードの間はANDにするという場合は、boolクエリのmustとの組み合わせになります。)

エリア条件のオートコンプリートの例

オートコンプリートの例としてエリア条件の例を挙げたのでここで少し寄り道します。

エリア条件というのは求人サイトであれば、勤務地とか企業のビルの所在地を検索条件に使うというやつです。

Elasticsearchだと、オートコンプリートには、Suggestersシリーズのサジェスト専用のクエリがあり、その中でもザ・オートコンプリート用のCompletion Suggesterというのがあります。

ただし、Suggestersシリーズのクエリは、性能等を考慮して専用のインデックスを作成することになるのと、クエリのDSLの構成および返り値のJSON構造ともに、通常の"query"系の検索と少し形式が違います。

私なぞは、どうせ専門のインデックスを作成することになるなら、元ネタになる住所コードマスタを入手するついでに、これを活用して、都合の良いインデックスを作成して、通常の"query"系の検索で検索してしまえと考える派です。

ということで、ひとつの案ですが、次のような例を挙げてみます。

f:id:azotar:20190126152838p:plain

これ自体は、階層ごとのデータを作ってやってそれを、prefix検索すると(部分一致より高速と思われるというメリットも含めて)、オートコンプリートのリストの元ネタおよび付帯情報が得られるというノウハウかと思います。

だんだん確定する部分を伸ばしていくということにも向いています。

例えば、次のとおりです。

「みな」と入力

→東京都港区

→さらに東京都港区の配下の候補一覧表示され、もう少し詳細なエリアを指定したければ

候補から選択 or 「東京都港区しん」を入力して「東京都港区新橋」で確定

この実装パターンの発想は他にも有用な用途があるかもしれません(あると思っています)。いつかデザインパターンだかイディオムだかとしてまとめてみたいと考えています。

また、この例であれば、そもそも入力中のひらがなでも候補を出すことが可能です*1

なお、基本に戻って、Suggestersは、通常の検索とやや異なります。過去にまとめた記事があるのでリンクしておきます。

itdepends.hateblo.jp

memo: オートコンプリートのパターン

オートコンプリートの要件に従い、Elasticsearchのどの方法でオートコンプリートを実現するかというはもちろん重要です。

ただ、その前に、オートコンプリートのスペースが限られた領域で、どういうUIにするか/ありうるかという自分なりのパターン分けをしておくと、本当に必要な要件を見出しやすくなると思います。

私は、次の4つをイメージして、あるサイトにマッチしたものは、これらのうちどれか、どれの延長線上かという捉え方でアタマの整理をすることにしています。

f:id:azotar:20190126143426p:plain

※ 戦略2、戦略2’では、候補のリスト表示を階層表示風のイメージ図にしていますが、これはあくまで元のデータが階層的になっていることを活かした候補一覧を表示するという意味で示しています。必ずしも実際のUIとしてリスト内の表示を階層型にすべきという主旨ではありません。

検索プロセスの見極め

話を元に戻します。

次に、このサイトでの「検索プロセス」のカタチ・型を見定めます。 

Elasticsearchや最近のSPAのUI等、ブラウザ上・サーバサイドともにやれることの選択肢は広がってきていますが、私の主張は、ある検索いちサイトでは、全ての検索要件をこれだと決めたカタチ・型にそろえるように寄せていくことで、設計・実装してくスタイルが何かと取り回しがききやすく、得られる検索UXの満足度が高くなるんじゃないかというものです。

私のお気に入りの「検索プロセス」の型は次のような図のものです。私は空手の心得がある訳ではありませんが、空手の型・流派みたいなものなのかもしれません。

※図中の点線で示している部分は、オプション(無くても機能は成り立つが、これらの扱いは議論して、重要だと考えるなら機能や仕掛けを設けること筆者はオススメしているもの)です。f:id:azotar:20190124005443p:plain

私のお気に入り検索プロセス解説

図の中で、ここまで述べたこと以外に、あるいは述べたことに重ねて、それとなくマイベタープラクティスとして示唆している点は次のとおりです。

  1. 全文検索には、(AND検索を主軸にすること、アプリで検索語派生する方針もあり、)multi_matchを使おう。multi_matchでヒットさせるフィールドの並べ方(正確にはboostの係数)で、優先フィールドを調整しよう。このフィールドの配列は、クエリビルダーの外で管理して、並び替えや係数を調整しやすいようにしよう。
  2. オーガニック検索は、複数ワード入れられた場合はAND検索です。ただし当たり前ですが、AND検索は検索結果が絞り込まれるので、利用者の想定以上に検索にヒットしないという結果になることもしばしばです。ということで、検索結果が0件の場合などにレスキュー処理(図中の二次検索など)の取り扱いを考えてやりましょう。まあ、実際にどこまで対応するかは別として、「救済」が必要なのかどうかというのは議論のポイントになると思います。
  3. 「救済」のための二次検索は、一例としては、派生したワードを含めて全てORで検索します。Elasticsearchの場合、1の例でのbool.mustをbool.shouldに組み替えるだけで全てをOR検索にするクエリが出来上がります。
  4. 図ではどちらと結論づけていませんが、レスキューの際に、検索結果が0件だったことを示すのか、なんとか検索結果が得られるような二次検索の検索結果を代わりに返してやるのかというのも「型」としての見定めどころだと考えています。

コラム: ElasticsearchのCompound query clausesとLeaf query clauses、match系・term系のクエリの検索ワードと対象フィールドの指定の仕方

上記では、Elasticsearchを下地にした、検索プロセス云々を論じて、極力リアルにアーキテクチャを示したつもりです。

ElasticsearchのクエリDSLの記法でどんなものがあるかを念頭に置いた上で、その中でもこれをこう組み合わせて...という組み合わせの結果です。

経過を全てお見せするのは難しいですが、組み合わせの試行錯誤の素材になった、ElasticsearchのクエリDSLのどの記法で、レコードのどのフィールドを指定の検索ワードで検索しにいくことになるかを復習しておきます。

f:id:azotar:20190130000925p:plain

私などは物覚えも物忘れもよろしくないので、時々、上のような図で再確認をすることにしています。

※ 先に述べた検索プロセスの型を持ちましょうというのは、このようなどのクエリをどう使うみたいなところの逐次のモグラ叩きから解放されるのではという考えもあって主張しているところもあります。

また、参考に過去記事をリンクしておきます。

itdepends.hateblo.jp

itdepends.hateblo.jp

検索のオニオンアーキテクチャ

ちなみに、このあたりで、アーキテクチャっぽい図をまとめて、チーム内の役割分担や責任範囲をすり合わせていくと良いと思います。

個人的には、オニオンアーキテクチャ風の書きっぷりの図でまとめると、余計なバイアスが入らない範囲でアソビを残しつつ気持ち合わせしたい程度には言いたいことが言えて良いのではと感じています。

f:id:azotar:20190130015302p:plain

実装や利用フレームワークはこの絵では規定しないのですが、ドメイン知識を示唆できるのと、どの塊・どこが内部/外部のインタフェースとなるかというところや、要件に見合った依存関係の方向を示せるので、参画メンバのキャラクターにもよりますが、この類の図を用いて認識合わせするのが有効だと考えています。

検索プロセスの設計アプローチイメージ

前の説の検索プロセスの型を定めると良いという話の少しだけ続きです。

自分(?)の得意な型を定めるというような言い方をしていますが、つまるところ、Elasticsearchのクエリビルダーの機能はできるだけ1機能に集約しようという主旨です。

↓こんな感じです。

検索機能の設計アプローチイメージ

f:id:azotar:20190125010120p:plain

※ 検索サービスや検索メニューとありますが、ここではサービスとメニューという用語にそれほど厳密な意味はありません。前者が企画目線で後者はやや機能や実際の操作方法目線ぐらいの意味です。

前の方で述べたことの言い直しですが、そのサイトの検索サービスのEsクエリのテンプレートおよび検索プロセスはできるだけ骨組みとしては一本に集約するようにしましょう。 逆に、それ以外はアドホックに、付け足ししていく方針で、設計も実装もアプローチしていくと、維持や継続的な改善含めて費用対効果が高いような検索サイトとして運営しやすいのではないか、という主張になります。

検索クエリの構造の標準化

クエリビルダーを構築しましょうのように申していますが、この記事のターゲットの検索サイトの範囲であれば、無理に汎用的なものにする必要もないと考えています。

といいますか、汎用クエリビルダーをどこまでどうしようかというのは、開発効率やもろもろ考えるとアーキテクトの人のウデの見せ所ではあると思いますが、一方でここまでのとおり、検索プロセスの型を定めるとおおよそクエリのDSLのテンプレートのJsonのカタチが決まるので、検索メニューに応じて異なる部分を差し替えるというやり方で泳げる(つまり、クエリビルダーClassのようなものでなんらかモジュール化はした方が良いものの、じゃあそれが、他の検索サイトPJで変更なく使える程のものにする必要はないのでは?)という 範囲になります。

SQLもそうですが、検索する・リストを返すための「クエリ」そのものは、文字列構築の魔法使いの世界だと思います。

宣言型で実現できることによる見通しの良さと、複数の検索メニューのうち共通する部分をドメイン知識として、多少むき出しでも良いので、プログラムに見栄えに可視化して残すというのが少なくともこの界隈の2019年1月時点ではうまい方法のように感じています。

ということで、先述の私のお気に入り「検索プロセス」の型の場合の、オーガニック検索のクエリDSLの「テンプレート」は次のようになります。

f:id:azotar:20190130003116p:plain

なお、ここに公式のElasticsearch Clientsの一覧がありますのでリンクしておきます。

上記のような主張のとおり、私自身は例えば、Javaであれば、Java REST Clientの「High Level」よりも、「Java Low Level REST Client」の方がクエリDSLを自分で取り回しやすく、プログラムの見栄えにドメイン知識がにじみ出る分、好んで利用したい気持ちです。

www.elastic.co

補足1: 型はめ論法の落とし穴に陥らないように点検しながら進める

ここまで、型を決めろとか、型が決まれば全て解決というような言い方をしていますが、念のため自問しておきます。

手順やプロセスありきで進めて、それが当てはまらない場合を見逃してしまうという、エンジニアリングあるあるにならないように気をつける必要はあります。

確かに、実際のところはケースバイケースです。 ただ、冒頭に述べたように、どのような種類の検索サイトなのかを客観視した上で、いけそうだということであれば、型ファーストで進めていくことも可能かなと考えています。

詳しくは説明しませんが、私なぞは、例えば、次にあげたような表を埋めていくなどしながら、要件とElasticsearchの機能や仕組みのマッピングをとっていく中で、イケそうか点検しながら検討することにしています。

f:id:azotar:20190125010105p:plain

f:id:azotar:20190125010112p:plain

点検のポイントとしては....

  1. 優先するフィールドを見極める
  2. (特に優先する)フィールドについてアナライザーのパターンの最小公倍数を明らかにする
  3. term、range、geoXXのような、特定の属性に対しての厳格な検索の要件を洗い出す。
  4. メインクエリの検索かファセット(aggsやpost_filter)での絞り込みかの役割分担のおおよその目処をつける。

です。

また、余力があれば、開発初期のダイナミックmappingテンプレートの設定をどうするかも見極めると良いでしょう。

...と言いながら、ひとまず機会的に次などを設定しちゃいますが....

PUT my_search_index
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_kuromoji_tokenizer":{ "type": "kuromoji_tokenizer", "mode": "search" },
        "my_ngram_tokenizer":{ "type": "ngram","min_gram":2,"max_gram":3, "token_chars":["letter","digit" ]  }
      },
      "analyzer": {
        "my_ja_default_analyzer": { 
          "type": "custom", "tokenizer": "my_kuromoji_tokenizer",
          "char_filter": ["icu_normalizer","kuromoji_iteration_mark","html_strip" ],
      "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "ja_stop", "lowercase", "kuromoji_number", "kuromoji_stemmer" ]
        },
        "my_kuromoji_readingform_analyzer": {
          "type": "custom", "tokenizer": "my_kuromoji_tokenizer",
          "char_filter": [ "icu_normalizer","kuromoji_iteration_mark","html_strip" ],
          "filter": [ "kuromoji_readingform", "kuromoji_part_of_speech", "ja_stop", "lowercase", "kuromoji_stemmer" ]
        },
        "my_ngram_analyzer":{ 
          "type":"custom", "tokenizer":"my_ngram_tokenizer",
          "char_filter": ["icu_normalizer","html_strip"], "filter": [ ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "hybrid_style_for_string": {
            "match_mapping_type": "string",
            "mapping": {
              "analyzer": "my_ja_default_analyzer",
              "fielddata": true, "store": true,
              "fields": {
            "readingform":{ "type":"text", "analyzer":"my_kuromoji_readingform_analyzer" },
            "ngram":{ "type":"text","analyzer":"my_ngram_analyzer" },
        "raw": { "type":"keyword" }
              }
            }
          }
        }
      ]
    }
  }
}


そもそものMapping全体については、雰囲気だけですが、過去にまとめたものがありますので、リンクしておきます。

itdepends.hateblo.jp

補足2: bool、shouldの捉え方

点検では、アタマの片隅で、要件を実現するクエリDSLを適宜思い浮かべながら進めていくのですが、この際、boolとshouldについてこのような理解をしておくと、混乱しにくいのではというポイントを以下に図にしてみました。

shouldはOR検索条件のようで必ずしもそうではない f:id:azotar:20190130011252p:plain

SQLをビルドする時と異なり、ElasticsearchのクエリDSLを見定める際は、まずmustで考えて、違和感があるものはshouldに追い出す...ぐらいが良いように思います。.... という話。


検索は検索なんだけど、軸となる検索条件の塊を組み合わせて元の集合からフィルター*2しているようなイメージで設計しよう f:id:azotar:20190130011308p:plain

補足3: ファセットとpost_filter

検索結果のファセット(Elasticsearchであれば、aggsで実現するのが定石)とpost_filterの見定めを行います。

ファセットの大まかなパターンとしてどのようなものがあるかの自分の中でのパレットを描いておくのが良いと思います。概念的なものよりも、UIのイメージで捉えておき、このフィールドのファセットは、スタイルAのドリルダウン...などと整理していくのが良いでしょう。

f:id:azotar:20190130021530p:plain

私はpost_filterについては次のような理解(検索条件のピボットを重視するUX/UIの場合に重宝する)でいます。 f:id:azotar:20190130011336p:plain

点検の結果としてのオーガニック検索のクエリDSLのテンプレートブラッシュアップ

点検を通して、少し前で述べたオーガニック検索のクエリDSLの「テンプレート」は、次のようなより具体的なものにブラッシュアップされるとともに、文字どおりこのテンプレートの応用の範囲で今回のサイトの要件を現実的にコントロールしていけそうだという目処が立ちました(というストーリーです)。

f:id:azotar:20190130004459p:plain

また、上記の図のままではないですが、(補完がきいたとしても)初出のクエリDSLJSONをゼロから手打ちするのはめんどくさいので、シンタックス的に誤りのない(ハズ)のある程度盛りクエリのテキストを貼り付けておきます。

POST car_and_animal/_search
{
  "size": 10,
  "from":1,
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "bool": {
                "must": [
                  {
                    "boosting": {
                      "positive": {
                        "multi_match": {
                          "query": "鳥 産む 食べる",
                          "fields": [
                            "content_ja",
                            "content_ja.meishi"
                          ],
                          "boost": 1,
                          "operator": "or"
                        }
                      },
                      "negative": {
                        "match_all": {}
                      },
                      "negative_boost": 0.2
                    }
                  }
                ]
              }
            }
          ],
          "should": [
            {
              "match": {
                "title_ja": {
                  "query": "ヒゲワシ カリフォルニア",
                  "operator": "or"
                }
              }
            }
          ]
        }
      }
    }
  },
  "aggs": {
    "tokuchougo": {
      "significant_text": {
        "field": "content_ja.doushi_nado",
        "size": 10,
        "filter_duplicate_text": "true",
        "background_filter": {
          "term": {
            "content_ja": "車"
          }
        }
      }
    }
  },
  "_source": [
    "title_ja"
  ]
}

※このクエリ自体には意味はありません。

設計の流れ・アプローチの全体像のおさらい

ポエム度低減のため、できるだけElasticsearchの例を先行して述べてきました。気まぐれな流れで申し訳有りませんが、実は次の図のような流れで設計なりなんなりの検討を進めているというストーリーにそったものでした。

f:id:azotar:20190125005838p:plain

※ 図中の 1、2、3、A、C あたりをつまみ食いして述べてきたつもりです。

いうまでもなく、これが唯一無二の方法でもないですし、この流れにそえば手戻りも最小だったり失敗しないというものではないです。

ただ、試行錯誤でぐるぐる回ったりしている部分はあるにせよ、経験豊富な方はみなさんおおよそこんな感じで検討されているではないでしょうか。

さて、図で示した、太線で結ばれている部分が、検討のメインフローだとすると、メインフローに寄り添ったトピック:図中の【5】のところが、今回テーマにしたタイプの検索サイトでは見逃せない要素だと考えています。

次項では、この部分についてだらりと述べてみます。

検索用ドキュメント標準化(仮称)の営み

ElasticsearchではJSON形式のドキュメントをざっくりインデックスに投げ入れることができます。

また、LogstashなどログアグリゲーターやIngest Nodeなど、あるいは中の仕掛けはよく知らないのですがkibanaのデータロードツール的なものなどで、データソースのデータを取り扱いやすいデータ形式にお手軽に変換してやることもできますので今や便利づくしです。

とは言え、なんだかんだいっても半定形とも言えるログ型のデータと異なり、今回対象としているような検索サイトの例だと、データソース側はいびつなビジネスロジックの結晶とも言える形式になっているものもしばしばあります。せっかくのIngest Nodeなどの仕組みはありつつも、軽く下調べした際に妙な臭いが嗅ぎとれる場合は、自前のアプリケーションで変換してやる方に舵を切るというスタンスもありだと思います。

つまりこういうことです。↓

f:id:azotar:20190125014234p:plain

ともあれ、自前のアプリで変換等してやるかはともかく、ある程度腰をすえて検索エンジンを導入する場合は、検索要件に適した、かつ極力検索結果のリスティングにそのまま埋め込むだけで利用者向けの表示がなりたつようなドキュメントのカタチにしてやるのが遠回りなようで近道だということは言えると思います。

注:

この記事では、検索用ドキュメント標準化(仮称)的なものは、自前アプリでできるだけ頑張ってやる方向で割り切った方が今回のテーマにした用途には合いそう、というストーリーでこの後も続きます。

とは言え、ググった流れでたまたまこのページにたどり着いた方向けに誤解のないように、念のため公式のIngest Nodeのリファレンスへのリンクと、このブログの過去記事で、Ingest Nodeの勉強のために早見表をまとめたので、こちらのリンクを付けておきます。この記事のノリにしっくりこない方は、車輪の再発明にならないように、公式リファレンス等もあたってみてください。

www.elastic.co

itdepends.hateblo.jp

補足1: 標準化した方が良いパターンについて

前述の図にそれと無しに書きましたが、自前アプリで標準化しても良いかも...の見極め観点として、図の右上あたりですが、標準化パターンとして私の考えで分類して見ました。

特に、重要な見極めポイントではと考えているのは、図中に「データソース側固有のビジネスロジックの圧縮」としたものです。

これは、例としてしっくりくるか分かりませんが、例えばの例でいうと、RDBのあるテーブルで、カラム1の値がAの場合、カラム2、3、... の値がQならこのレコードでは「カラム2」の意味は「XXX」だが、カラム1の値がBの場合、カラム2の値がやはりQだったとしても、このレコードでは「カラム2」の意味が「YYY」となるというような場合に、Elasticsearchのインデックスにこのままのフィールド単位でデータを持ち込むことは現実的でありません。

なにやら変な例を持ち出したので、そんな経験があるんかいと思われそうですが、それはともかく、似た例でもう少し軽めのものとしては、◯◯項目群有効フラグのようなカラムがあって、これが「無効」の場合、関連するカラム2、3は値が登録されていても表の検索サイトでの表示には使ってはならん...ぐらいのことは歴史のある上流システムではあるあるだと思います。

標準化パターンとしてあげたもののについて、ざっくりした例を次の図に示します。

f:id:azotar:20190126065358p:plain

また、これらの解説を長々とまとめてみたのですが、本当に長くなったので付録に回しました。

検索用ドキュメント標準化パターン解説

補足2: インデックス更新のフレームワーク

自前アプリでの標準化に近いところの整理ポイントとして、(ビジネスルールで許容される範囲の割り切りはしつつも、)表示内容の整合性確保のために、更新トランザクションを確立したいという要件に対応するために、インデックス更新のやり方にこだわりがある場合があります。

こちらもあまり言うとボロがでそうなので、雰囲気の範囲で自説を述べておくと、更新処理のフレームワークを確立しておくと良さそうです... というところと、私の好みは次の図の3つ目の方式です。

f:id:azotar:20190130235537p:plain

ちなみに、図の3つ目の方式では、それとなく論理削除方式を用いていることを示唆しています。これは何かとアンチパターンに繋がりうる論理削除方式を推奨している訳ではなくて、フレームワークやなんらかビジネスルール等の都合で、論理削除方式を取るなら、こういうやり方もあるのではという例です。

トランザクションには、「結果整合性」重視というスタンスもありますが、この例だとインデックスの更新に関して「結果整合性」の視点で見るのがテック的に正攻法の視点だと思いますが、一方で、次のざっくり「検索サイトの機能構成イメージ(※気持ちECサイトを想定しています)」図で言うと、検索サイトのビジネス目線でのトランザクションは、商品ページで発生します。

f:id:azotar:20190130234816p:plain

つまるところ、ビジネス的な「結果整合性」は商品ページで確保する、例えば、その商品の在庫が切れてしまった時には商品ページでエラーにする、といったアプローチを前提に、検索インデックスは論理削除方式にするというスタンスもありでしょう。また、論理削除方式をアンチパターンと知らしめている一つの理由に、検索時に「論理削除 ≠ ON」のデータを検索しなければならないというものがありますが、後々物理削除されることを前提に、このデータは現在カートに入れることはできませんが、本来の商品説明としてはこんな感じですという情報として検索結果リスティングには成り行き表示することにして、検索時には論理削除を意識しないという手もありそうですね。

なお、ここでは、データソースが一元化されていてかつデータソースの更新=検索エンジンの即時反映とすべきのようなものではなく、多少ひねくれたかつデータソースが複数ありこれらの更新契機が様々なものを想定してこのような話を書いています。前者のような素直でまじめな構成の場合のトランザクション制御としては、「version」を使った楽観的ロックでの制御ができます。根元の要件が素直な場合はversionを使ったロックを行うものと思われます。

この「version」については、ググラビリティが低いのと、公式リファレンスのどこに書いてあったかわかりにくいので、自分メモも兼ねてリンクをしておきます。

補足3: 自前アプリでの検索用ドキュメント標準化のフレームワーク

話はドキュメント標準化に戻りますが、ドキュメント標準化処理もフレームワーク化しておいた方が良いでしょう。トランザクションや例外処理のフレームワーク化という意味もありますが、ここでは、私の芸風にありがちな、よくあるパターンの骨組みを見つけて、あとは多少ナイーブで冗長でも、最小限のDSLで実現できないかを模索して、それを型にしたものをフレームワークと呼んでいます。

例えば、次の図のようなものです。

f:id:azotar:20190131002035p:plain

標準化パターンは、項目単位のものと、項目またがりのものと、項目は意識せずドキュメント内の全項目に適用するという種類に分けられるので、これらをパイプラインで最大2回並べるようなUNIXのパイプ処理風の考え方で、それぞれのノードにコンフィグやプラグイン的に編集ロジックを付け足しできるようにしておくという考え方にしておけば、大半のものは対応できると考えています。

あと、そういう世界もあるという話で申しますと、これぐらいのバランスの方が、(何かと力の及ばない)上流システムの設計書(≒EXCELの表)などから、これらの変換処理を生成したり、Elasticsearchのインデックスフィールド項目の仕様書的なものを作成して上納のための事務作業の手間減らしにはちょうどよかったりするというところもつぶやいておきます。

補足4: 同じドキュメントでも項目群別に別インデックスにする考え方もある

最近のElasticsearchでは、1インデックスに1タイプが基本になったので、業務アプリ屋的にはむしろ迷いがなくなってありがたい状況です。

また、負荷分散や可用性方面の話、クラスタやシャードやノードといったところの世界観はElasticsearch自体が面倒を見てくれるので、(Elasticsearchに限らずですが)油断や過信は禁物なものの、1インデックス1タイプでお任せ設計を基本線とすれば良いと思います。

ただし、それでもリソース節約や外部要因(おもに上流のデータソースの事情含む)に引きずられて、ユースケース的には同じタイプなものの、実は全フィールドに値が入っているようなレコードはまれで、領域だけ確保されてスカスカのインデックスとなるという場合もあるでしょう。

スカスカのインデックスが本当にリソースが大ムダになるようなElasticsearch/luceneの仕様かどうかは確かめていないのですが、実際に期待した性能が出ない場合などに札束で殴るわけにもいかずという場合に、アプリでのインデックス分割を考えることになるかもしれません。 ということで、(下のレイヤのシャードやノードの分散・分割はやはりElasticsearch/luceneの世界なので)Elasticsearchのアプリレベルでのインデックス分割が効果がでるかはさておき、こういう分割パターンがあるよねというパターンとチーム内で議論できるようなボキャブラリーをしたためておくのは悪くないと思います。

同じ「タイプ」を別インデックスに保持する方式バリエーション f:id:azotar:20190126162046p:plain

※この分野では、水平分割・垂直分割という用語があるように記憶していますが、ここでは、分割方法の分類よりもどこにアプリケーション視点での分割できる切れ目を作るかという視点なので、自分で言い回しを定義して呼ぶことにしました。

また、この節の主題とはやや異なるのですが、「インデックス分割」から連想される、別のフォーメーションも示しておきます。

RDBのマテリアライズドビュー風に派生して併用 f:id:azotar:20190131014936p:plain

検索結果画面のUIについて

長くなったポエムもこれで最後です。

ここまで、色味やトーンなどのデザインの機微はあるものの、ワイヤーフレームレベルではすでに決まったものという体で特にふれなかった、検索結果画面のUIについてです。

検索結果画面とはつまるところ何なのか

次の

itdepends.hateblo.jp

という過去の記事でもそれとなく主張したのですが、検索サイトの少なくとも初期ローンチ時のフォーマットは他のサイトの標準的なUX/UIに慣れた人向けに、よくあるパターンにはめ込むことになると考えています。

この姿勢はひょっとすると画期的な案を潰しかねない面もありますが、逆に言うと、奇をてらったものに過ぎないのか本当に画期的な案なのかは、一旦「よくあるパターンにはめ込み」した上でそれと画期的な案のプロトタイプを比較するということで炙り出されるとも言えそうなので、そう言う意味でも思考停止にならない程度に、標準パターンにはめ込むことは悪いものではないでしょう。

ということで、パターンはめ込みスタイルで検討していけばいいじゃんというのがこの記事での再度の主張なのですが、もちろん実際の検索サイトでは、色味やトーンなどの見栄えや、ファセットや検索BOXの配置、今であればアニメーションなどを練りこんでいく必要があり、ここの試行錯誤がサイトの成功要否に関わりますので手を抜けないところでもあります。

また、チームに全方面に詳しい・明るいUX/UIエンジニアがプロジェクトにいてリードしてくれれば良いですが、必ずしもそうでないでしょう。しかし、見栄えの話は意見が言いやすいことから、いろいろ発散してしまいがちで、気がつけば「実際はUXに寄与しない誰かの好みの見栄えの確保」のために、せっかく上記で点検・整理した検索プロセスを崩さざるを得ないということにもなりかねません。

ともあれチームビルディングや合意形成のうまいやり方で乗り切るというところも一つですが、そこにどういう役割でかかわるにせよ、チームの一員としては検索結果画面について自分なりのブレないメンタルモデル*3をしっかりイメージしておくと良いと考えています。

私の場合は、

検索結果画面は、

検索処理を伴うものの、実際のところは

「ユーザーが気になるものを意識的・無意識的に机の上に広げたただのリスト」

というイメージで捉えています。

エンドユーザーは机の上あるいは自分の手のひらの中で、ドキュメントを転がしている、そのための場が検索結果画面、というものです。

このイメージをイメージにしたのが次の図です。

f:id:azotar:20190131015559p:plain

イメージを無理にイメージにした図というようにくだらないシャレなアレな図なので読者のみなさんに伝わるかは自信は無いですが、例えばこのような頭の整理をしてみると良いでしょうという主張としてあげさせていただきました。

検索結果画面よくあるパターンのバリエーション(の可視化)

上記の捉え方がイケているかはともかく、ひとまず自分なりのイメージが出来上がると、想定ペルソナとの組み合わせで、必須なあるいはサイトの目的にあうなら確実にあったら良いと思われるUI要素がニョキニョキと生えてきて、次の図のように、結果的に「よくあるパターン」のバリエーションの範囲に収束しそうな気がします。(しませんか???)

検索結果画面よくあるパターンのバリエーション f:id:azotar:20190131015643p:plain

あとは、自分がどの立場かにもよりますが、例えば検索UXとElasticsearchを軸にしたディレクター的立場なら、デザイナーさんやCSSデザイナーさんに、サイトのコンセプトとともに、このバリエーションの図およびバリエーションの図から引き出した今回の利用候補のコンポーネント一覧を伝えて検討してもらう、というような段取りになるかと思います。

まとめ

ある種の検索サイトにターゲットを絞ったとして、どのようにElasticsearchを活かしてサイトをディレクションするかについて自分の意見をまとめてみました。

Elasticsearchをダシにしつつかつターゲットを限定した割には、毎度のごとくイメージ図ばかりになってしまいましたので、テック系の内容やもう少し具体的な例で加筆できそうなものがあれば、(ここで述べているストーリーが古くならないうちに)随時追記したいと思います。ただし、意図せぬお漏らしなどはできないので、実際にすごいことをやっているかどうかは別として検証系はこの記事用に全く無関係なものの似た構造のデータを見つけて来てやってというところになるのでやりたくても悩ましいところ。

また、Elasticsearchを利用させてもらっている者として、その魅力を伝えるようなアピール作文ができたら追記したいです(優等生発言!)。

参考リンク:古くならないうちに....

この記事が「古くならないうち」にと言いましたが、今やこの記事の講釈を垂れたような内容(およびそれ以上の発展的なもの)は、例えばトップランナーの方が紹介されている次のようなもので、実際に簡単に試すことができるところまで来ているようです。

Reactive Searchの紹介

qiita.com

Reactive Search のVue.js版の公式サイト ↓

https://opensource.appbase.io/reactivesearch/vue

(この記事執筆時点では、私はどちらかといえば、Vue.js派なので...)

また、この記事ではスコープを絞り込むことで少ないリソースで検索サイトを仕上げるというスタンスでまとめていますが、そんなチマチマしなくとも、公式のクラウドサービスのうちのさらにいくつかサイト検索系の製品では(私は触って見たことがあるわけではありませんが、おそらく)いろんなユースケース用のパターンがプリセットかつオールインワンで同梱されており、Elasticsearchの生のコンフィグファイル設定ではなくGUIの管理画面などでサクサク検索サイトが実現できると思われます。 (いろいろ類似の例がありますが、私のなんとなく知っている範囲では、Cloudera社のHadoop系のスイーツのサービスモデル・ビジネスモデル、エコシステムと似た動向を感じています。)

自分の書いた記事の自己否定ではないですが、いくつかある検索エンジン、またluceneをベースにしたものの中でもElasticsearchはサービスのエコシステムが強力そうなので、まずは公式サイトを当たってみるのが良いと思います。

www.elastic.co www.elastic.co


========================= 本編終わり ==========================


付録

標準化パターンの解説

本編で「標準化パターン」として私見を述べましたが、これらについて解説(もし新人向けに話したら老害一歩前の説教か退屈な昔話風)しています。

観点 解説
レコード名寄せ そもそものデータソース側がそれでええんかいというところはありますが、同じデータ(とみなせるもの)が複数存在する場合は1件のドキュメントになるようにレコードの名寄せをしましょう。

名寄せっぽいものとして、Elasticsearchの検索機能側には、collapse機能があります。こちらは、同じ著者の複数著作を著者単位に折りたたんだり、複数職種を募集しているある企業を親検索結果として見せるという用途に絞った使い方かと思います。
平坦化 Elasticsearchでは、NestedなデータタイプやObject型の階層データを扱えますが、何かと得意ではありません。得意でないというと語弊があるかもしれませんが、ECでの商品検索のように属性検索と全文検索を併用するというような泥臭系の検索ニーズは検索対象のデータの構造化や階層化に必要以上にこだわりすぎない方が良いのではと考えています。 この世界はオブジェクト指向ではないと思います。

... ということで具体的には、「a.b.c」フィールドの値を、「a_b_c」フィールドに格納し直す、人の名前で「氏名」が「氏」と「名」にサブプロパティに分けて保持しているというようなものを結合して1つのフィールドに統合するというのは考え方の一つとしてあるかと思います。(後者の例はPainless Scriptでも平易に実現可能ですね。)
表示名派生 元のデータソースでコード値持ちのものについては、表示名に置き換えたフィールドを派生してやりましょう。これで、フリーワードでの検索メニューでも該当のフィールドを検索にひっかける土壌ができます。

なお、長くなるので詳しくは書きませんが、コード値と表示名の対応表がデータソース側でどういう運営になっているかを確認しましょう。

また、検索サービスとして、同じ意味を表す表示名の変遷があった場合にどういう扱いにするポリシーとするかを整理しておきましょう(例えば、埼玉市からさいたま市に変わった場合に、お店の住所フィールド自体は最新化するでしょうが、埼玉市でも引き続きヒットさせるようにするか、するとしてどこの何のしかけでそれに対応するか)。
簡易全文検索フィールド かつての「_all」フィールド相当をイメージしたものです。
Elasticsearchには、multi_matchなど、複数フィールド(個別指定、フィールド名ワイルドカード指定ともに可)で同じ条件で検索して(一方、個別にブーストできる)ものもあります。 

ここでは、それらはそれらで活用するとして、様々なところの性能などのトレードオフ等も考慮しつつ、元のデータソースでは、フィールドA、フィールドB、フィールドCのように別フィールドに格納されているものの、属性検索の要件があきらかに発生しないと思われるものについては、一つのフィールドに片寄せしたようなドキュメントになるように編集したものをインデックスにPOSTするという考え方に対応するという考え方もあります。

これにより、検索側のクエリが検索ならではの要件にシンプルになるようにインデックス時に頑張っておくというスタイルもあるでしょう。
データソース側固有のビジネスロジックの圧縮 背景としては前項と似たようなもの。
人材募集サイトで、お金を多めに払ったスポンサー企業の募集と通常の募集を検索時に区別してやるとして(つまり検索シーズからいうと優待顧客とそうでない顧客のYES/NOの区別さえつけば良いという場合に)、データソースのビジネスロジックの都合で、フィールドAがX、BがY、CはZ1またはZ3、ただし...のような判定で「優待顧客かそうでないかの判定」を行う必要がある場合があります。
これを検索側に持ち込むのは得策ではない。... ということで、このような例の場合は、インデックス時にBooleanのフィールドに変換してやるというある種の正規化をしてやるという手はありますよねという話。

ちなみにベタなロジックでドキュメント自体を編集するというのもあるが、ElasticsearchだとPercolatorをうまく使って宣言的に条件を定義しておいてというやり方も使えるのでせっかくなら活用したいところ。
オフライン分類 これまた背景としては前項と似たようなもの。
元のデータソースのあるフィールドをもとにこのドキュメント自体のカテゴリ分けやタグ付け、ラベル付けをしてやる。データソースの方では厳密な値のみの管理で大分類のようなものは管理していない・しようもないような場合でも、検索ニーズではビッグワードや大分類レベルで検索できると嬉しいという話がしばしばあって、検索側だけで頑張る場合は、大分類ワードをデータソースの該当属性の対応付けを元にOR検索になるように展開してやる必要があるのと、検索側に展開のための知識を保持して(ロジックを作って)やる必要があるので、それをどう評価するかという話かもしれません。

なお、OR検索がめんどくさいと言いましたが、大ジャンル→配下の小ジャンル群(配列でなくても空白区切やカンマ区切りの列挙で良い。要素数も特に気にしなくて良い。)をドキュメントとしたジャンル対応インデックスを作ってやることで、このインデックスを独自類義語辞書風につかって、取得した小ジャンル群を"terms"クエリでマルッと検索することができなくはないと思いますので念のため補足しておきます。(ただし、たすき掛けの検索になるので検索時性能としては、冒頭に述べたようなオフラインで事前に分類してやるというチョイスは頭に入れておいた方が良いかもと思います。
ドメイン情報フィールドの除外 うまい言葉が見つからなかったので妙な呼び名になっていますが、主旨としては、データソースのフィールドのうち明らかに表側の検索サービスに不要な項目は、ドキュメントそのものから取り除いておきましょうという方針です。

例えば、ECの商品情報でいうと、データソース側の商品管理システムでは、商品情報最終更新オペレータ名などを保持していると思いますが、このようなフィールドは検索エンジンのインデックスにつかづける前に削除するクリーニングをしましょう(もうちょっと言うと、このようなクリーニング処理を「宣言的」に設定するだけで対象項目を調整できるような仕掛けの要否を整理しておきましょう)という話です。
異体字の派生 お店名や事業者名に含まれる漢字の異体字については都合よくヒットさせて欲しいね(例: 渡辺で渡邊)という要望がつきものかと思います。
教科書的にはchar_filterで頑張るのが基本かもしれませんが、検索対象のデータやAWS Elasticsearch Serviceを利用する場合などは外付けの対応表ファイルを使うのも何かと難しいです。

ということで、異体字を一般にもっとも平易な漢字に変換したものをフィールド派生してやるというのは、案としてアリです。
あくまで対象フィールドを限定して、コメント欄等は対象外で良いと思いますが、得てして事業者名等については、実際のUXとしてどうかはともかく、奇妙だが譲れない(ただし、検索エンジン全体の設定を変える程ではないし、そうしたくない)という要望が出がちだと思いますので、そういう場合の逃げ道にもなると考えています。

なお、ここでは異体字は、派生させる方針としましたが。別案としては、ANALYZERで、kuromoji_readingform token filterの読み仮名化したフィールドをインデックス化するという手があります。kuromojiの辞書の読み仮名の範囲に限られますが、「渡辺」で標準フィールド格納の「渡邊」を検索して空振りしても、読み仮名化したフィールドの検索でひっかけることができます。
カナ項目の清音化 kuromojiやicuなどのANALYZERでは、残念ながら(?)、清音化まではやってくれません。
ここで言う清音化とは「ベット」や「バック」で「ベッド」や「バッグ」をよしなに検索できるようにしましょうという用途のものです。
これぐらいならプラグインを自前で作成しても良いのかもしれません。一応ここでは、ElasitcsearchにPOSTする前の前処理でいろいろやってみるという話の流れなので「ド」を「ト」に置き換えたような「清音化済みフィールド」を用意してやる、あるいは少しだけシンプルに間違えがちな単語に置き換えた派生フィールドを作ってやるというのは案としてあるかもしれません。
もっと素直に「Fuzzy検索」する手もありますね。
ただ、この類のものはどこで入り込んでくるかわからないので、全部をFuzzy検索にするのも...というところも悩ましい話かと思います。

いずれにせよ、他の表記の揺れに比べればニーズが小さいのかもしれませんが、「清音化」で救いたい検索ワードの入力誤り例はしばしば不特定多数が利用するサイトではあなどれないこともあるというところを主張しておきたいです。
aggsのbucket用にグループ化 データソースのRDBでは1つのカラムに0、1ビットでフラグ管理されている類の項目A、B、Cがあります。
検索サービスとしてみると、これらはaggsの同じbucketに分類したいという場合がしばしばあります。
このようなケースに対応しやすくするために、インデックスにPOSTするドキュメントは、A、B、Cの設定内容に応じて、これらを配列に入れてやるというアプローチです。

例えばレストラン検索サイトなら、A、B、Cは、個室有無、貸切可否、駐車場有無といったカラムで、これらを席・設備というbucketにします。

上記の表の中で簡易全文検索フィールドと言っているものについては次の図でそもそもどんなユースケースを想定しているかイメージを表してみています。

(この記事のためにフリーハンドで作成したので(?)、図の中では、「簡易全文検索フィールド」は、「全文検索保険フィールド(仮称)」という呼び名になっています。良い名前を付けてあげたいのですが、初見の人にも伝わるような名前は思いつかずというところです。何か非公開のドキュメントを転用したわけではなく、この記事のために書き下ろした都合やむなしということでご了承くださいませ。)

f:id:azotar:20190126074555p:plain

*1: 念のため、オートコンプリートならやっぱりSuggesters系とした場合の、ど真ん中の正攻法はこちらのまとめを参考にさせてもらうのが良いと思います。 https://qiita.com/kijtra/items/36dd35b3b9db75c88f55

*2:ここでは、クエリコンテキストとフィルターコンテキストの意味のフィルターではなく、EXCELのフィルターのような絞り込みのニュアンス

*3:メンタルモデルという用語の誤用かもしれませんが。ひとまず。

企業のカネと価値(ただしおカネ寄りの視点の意味)の動き・値踏みのオレオレメモ(1)

そろそろ財務諸表を雰囲気レベルで良いので「目利き」できるようになりたいということで、その辺の勉強メモ。

最終的な結果ではなく、理解を深めるために、図解などの試行錯誤の過程を残してみた。この過程をたどることで、従来より深い理解に至ることができたので、同じような悩みの人には有効かもしれないので公開する。

※自分の腹落ちを優先したので、用語などは正確ではないかもしれません。また、アカデミックな定説等からは外れている部分もあるかもしれません。

CFで捉える

BSがピンとこない人はCF(キャッシュフロー)で理解すると良い...というようなことを聞くので、CFがどんなものか確認。

f:id:azotar:20190103002705p:plain

... 頭が硬いのか、センスがないのか、まだピンとこない...

ただ、現代の企業の活動は、営業、財務、投資の軸で捉えるのは定石なんだろうなというのを再認識。

絵にしてみる

続いて、企業のカネまわりの活動について手を動かして絵に書き出してみる。

f:id:azotar:20190103002725p:plain

描いてみて分かったが(描かなくても分かるが...)、サイクルのようでサイクルではないし、メッシュ型のあるいは双方向のグラフ形状になるところもあるので、動的な表現が思ったほど馴染まないと思った。

自分の中の理解の話に過ぎないが、サーバレスアーキテクチャの形に近いんだよな〜と思った。

様々なパスを絵に書き出してみることができた。時間がある時にしかできないので、目的は果たせてないが多少スッキリした。

BS再び

前項で絵に描いてみたことで、分かった...というか諦めがついた。

(これまでの私見とは矛盾するが、)企業の活動やカネの動きを俯瞰するには、カネの入りと結果だけに絞った方が逆にわかりやすいかも。

ということで、先人の知恵にならい、BS視点に戻る。

f:id:azotar:20190103005120p:plain

※この形式の絵自体はいろんなところで見る形だと思います。ただ、BSをカネの動きとして捉える場合は、(横書きドキュメントで時間経過が左から右で表されるのと違い)実際のカネ(活動)の動きはこの図では右から左だということは時々思い出した方が良さそうです。... ということに今更気づいたという話。

少し寄り道

寄り道というか、前提となる、社会か経済かの中高生の教科書の最初のページに書いてあることの再確認。

f:id:azotar:20190103002730p:plain

自分が学生のころから、ここは変わってないような気がするが、その当時以上に、「カネ自体の市場」が実体経済より大きくなっているんだろうなと思う。

また、本来のカネの動きをつかむのには、「ビジネスモデル」の理解が不可欠だと思うが、一方で財務諸表レベルの初見の目利きで深く考えすぎるとかえって混乱するので、ここでは深掘りしないようにしよう。

そうそう、"ビジネスモデル"については、最近だと、次のものを参考にさせてもらっている。

note.mu

こちらで述べられている、「逆接の構造」や「八方よし」というのは、深い理解や分析には欠かせないなあと思う。

また、BSに近い考えの話としては「無形資産」(のれん代)も本来は見落とせないが、やはり切り口がぶれるので、ここでは深掘りはしないことにする。

財務3表の関係を俯瞰

BSを掘り下げるとして、どうしても性格上、釣り合っている部分がどこか気になる。3表のどこの値がどこにつながるかを確認。

ただ、どうも書籍によって違いがある(というか一般に用語に幅があり、一意の定義がない、というかそのような定義をすることが難しいようなので)、あえて目を細めてぼんやり眺めてみることにする。こういう時に、google 画像検索は便利。

財務諸表 関係 - Google 検索

自分の理解に合わせて財務3表の関係を図解しなおし。

f:id:azotar:20190103002744p:plain

もう少しかな...というところ。

BSを大きくする・小さくする

企業の活動は、BSを大きくするあるいは筋肉質にする活動だというようなことを聞いたことがある。

帳簿だけと向き合って机の上だけで物事を捉えるのは良くないと思うものの、CFのフローにならって、また、それらの中の主な活動ごとに、BSのどの領域が大きくなったり小さくなったりするのか(単純化して)書き出してみた。

f:id:azotar:20190103002750p:plain

書き出してみてやっと分かったのだけど、(今回のように単純化して見ると)「現金」を介した活動になるなあという実感。

企業や国は家計と違い資金集めに幅があるものの、やはり「現金」をどれだけ回せるか(あるいはそれ相当の構造を作れるか)は財務的な経営のうまさにつながるんだろうなという理解が進む。

この他、この絵を描いてみて、一般によく言われる次のようなことが多少なりともピンときた。

  1. 事業が成長していて、かつ営業が黒字でも倒産することがある。(例えば、現金が多くなく、仕入れなどのために流動負債が拡大していて、(いざとなったら)現金化できる固定資産も多くないというケース)
  2. 流動負債が大きいものは経営が暗転しやすい。
  3. 資本金が大きい→ 定性・定量的に、大きい会社というのはもちろん、返さなくて良いお金が豊富なので、経営の取り回しに余裕がある。
  4. 固定資産が大きい→ 定性・定量的に、大きい会社というのはもちろん、(いざとなったら)現金化できる。が、資産価値が思ったより低い場合は値踏みに注意が必要。→ドラマでしばしばみられるやつ。
  5. IPOや株式の分割で、返済不要なカネを集める。(もちろん、株主の期待に応えていく必要はあるが...)

企業のカネを通した評価

前項あたりがしっくりきだすと、企業の値踏みというものがなんとなく分かってくる気がする。

ここらへんをすっ飛ばして◯◯率が他社と比べてなんとかかんとかとやっているだけでは自分の性にあわないところだったが、BSと企業の経営のおおまかな関連が見えてくると、自分の感覚に従って捉えた方が良いような気がしてくる。

書籍などでの、企業の評価には「△△性」「◇◇性」... というのがあります...という入り口の場合、ROAは「△△性」「◇◇性」どっちだっけというのが気になって仕方ないが、自分にとっては別にどうでも良いことだった。

ここは人によってはしっくりこないかもしれない例えだが、ドラクエとかでのキャラメーキングやキャラ選択の際にどのスペックを重視するか、というようなものと同じ観点で企業の活動を理解するというのはアリだなと思うに至る。

ということで、次の表をまとめてみた。

f:id:azotar:20190103002758p:plain

通常の教科書だと、分類・指標・(指標の説明としての)観点...の並びで説明してあり(これはもちろん正しいのだけど)、ここでは、(モノの道理から考えると企業活動で重要そうな)観点、キャラ選択になぞらえたら何?、その指標値として財務分析でどのような指標値が使われることが多いか...という並びでまとめてみている。

※「ドラクエで例える」のところは、レベルが上がりやすいキャラ→戦闘を有利に進めるのに役立つ・早いクリアに貢献、HPが多いキャラ→やられにくい、素早さが高い→先手を取れる(アグレッシブな事業の回しがしやすい)、等の連想になっています。私と同じような視点でドラクエのキャラを見ているかにもよりますが、悪くない切り口だと自分では思っています。

並びを変えただけ、自分の言葉で言い直しただけだが、書籍にある表を写経したよりは随分自分の中では進歩した気がする。

この記事おわり。

参考文献・参考リンク

あとで記載。

elasticsearch.js(JavaScript版 Elasticsearch Clients)のAPI早見表的なもの

少々思うことがあり、Elasticsearchの公式JavaScriptクライアントで何ができるのか俯瞰したかったため、APIのパラメータ早見表としてまとめてみました。

見る限り、Elasticsearchの提供するすべてのAPIインタフェースに対応するものがあるようです。

www.elastic.co

6.5 API | elasticsearch.js | Elastic

バージョン6.5のドキュメントからまとめました。 (まとめていて思ったのですが、Elasticsearchが「機能的」に何ができるかを俯瞰するとした場合に、自分の得意な言語の公式クライアントのAPI一覧から入るのは、勉強の仕方としてはアリだなと思いました。)

念のための言い訳なのですが、正確なところは公式ドキュメントを適宜参照いただく前提です。 このAPIとこのAPIでできることの違いはなんだっけ...というようなところをパラメータの違いから目grepで一瞥できるようなことを目指しています。 (自分が使うつもりの気持ちで編集しましたが、逆にいうと間違っている可能性がありますのでご了承ください。)

画像版

f:id:azotar:20190101155814p:plainf:id:azotar:20190101155835p:plainf:id:azotar:20190101155854p:plainf:id:azotar:20190101155915p:plain

...むむ、画像サイズが思うようにいかないかも。

pdf版

github.com

JavaScriptシグネチャ風版


// "  33      1   "  
    client.termvectors( { body : {},  termStatistics :true, routing :"String", parent :"String", preference :"String", fields :"String_String[]_Boolean", [offsets=true] :true, [positions=true] :true, [payloads=true] :true, version : 99999, versionType :"String", realtime :true});
// " 21       2   "  
    client.mtermvectors( { body : {}, typedKeys :true, [fieldStatistics=true] :true, termStatistics :true,  id :"String", index :"String", type :"String", routing :"String", parent :"String", preference :"String", ids :"String_String[]_Boolean", fields :"String_String[]_Boolean", [offsets=true] :true, [positions=true] :true, [payloads=true] :true, version : 99999, versionType :"String", realtime :true});
// "  1       3   "  
    client.bulk( { body : "JSONLines",  pipeline :"String", waitForActiveShards :"String", index :"String", type :"String", routing :"String",  fields :"String_String[]_Boolean", _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean",  timeout :"2019-01-01", refresh :"String"});
// "  16      4   "  
    client.index( { body : {}, pipeline :"String", [opType=index] :"String",  waitForActiveShards :"String", index :"String", type :"String", routing :"String", parent :"String",  version : 99999, versionType :"String", timeout :"2019-01-01", refresh :"String"});
// "  4       5   "  
    client.create( { body : {}, pipeline :"String", waitForActiveShards :"String", id :"String", index :"String", type :"String", routing :"String", parent :"String",  version : 99999, versionType :"String", timeout :"2019-01-01", refresh :"String"});
// "  34      6   "  
    client.update( { body : {}, lang :"String", retryOnConflict : 99999,  waitForActiveShards :"String", id :"String", index :"String", type :"String", routing :"String", parent :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", version : 99999, versionType :"String", timeout :"2019-01-01", refresh :"String"});
// "  5       7   "  
    client.delete( { body : {}, waitForActiveShards :"String", id :"String", index :"String", type :"String", routing :"String", parent :"String",  version : 99999, versionType :"String", timeout :"2019-01-01", refresh :"String"});
// "  9       8   "  
    client.exists( { body : {}, id :"String", index :"String", type :"String", routing :"String", parent :"String", preference :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", storedFields :"String_String[]_Boolean", version : 99999, versionType :"String", realtime :true, refresh :true    });
// "  13      9   "  
    client.get( { id :"String", index :"String", type :"String", routing :"String", parent :"String", preference :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", storedFields :"String_String[]_Boolean", version : 99999, versionType :"String", realtime :true, refresh :true });
// "  18      10  "  
    client.mget( { body : {}, id :"String", index :"String", type :"String", routing :"String", _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", storedFields :"String_String[]_Boolean",  realtime :true, refresh :true });
// "  10      11  "  
    client.existsSource( { body : {},  index :"String", type :"String", routing :"String", parent :"String", preference :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", version : 99999, versionType :"String", realtime :true, refresh :true  });
// "  15      12  "  
    client.getSource( { id :"String", index :"String", type :"String", routing :"String", parent :"String", preference :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", version : 99999, versionType :"String", realtime :true, refresh :true   });
// "  11      13  "  
    client.explain( { body : {},  q :"String", [defaultOperator=OR] :"String", df :"String", id :"String", index :"String", type :"String", routing :"String", parent :"String", preference :"String",  _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", storedFields :"String_String[]_Boolean", analyzeWildcard :true, analyzer :"String"});
// "  30      14  "  
    client.search( { body : {}, typedKeys :true, explain :true, q :"String", [defaultOperator=OR] :"String", df :"String", [maxConcurrentShardRequests=The default grows with the number of nodes in the cluster but is at most 256.] : 99999, id :"String", index :"String_String[]_Boolean", type :"String_String[]_Boolean", routing :"String_String[]_Boolean", preference :"String", [expandWildcards=open] :"String", _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", storedFields :"String_String[]_Boolean", version :true, timeout :"2019-01-01", analyzeWildcard :true, analyzer :"String", ignoreUnavailable :true, allowNoIndices :true, terminateAfter : 99999, lenient :true, size : 99999, from : 99999, stats :"String_String[]_Boolean", requestCache :true, sort :"String_String[]_Boolean", scroll :"2019-01-01", trackScores :true, trackTotalHits :true, [batchedReduceSize=512] : 99999, [preFilterShardSize=128] : 99999, [allowPartialSearchResults=true] :true, suggestField :"String", [suggestMode=missing] :"String", suggestSize : 99999, suggestText :"String",  searchType :"String",  docvalueFields :"String_String[]_Boolean"});
// "  3       15  "  
    client.     count( { body : {}, minScore : 99999, q :"String", [defaultOperator=OR] :"String", df :"String",  index :"String_String[]_Boolean", type :"String_String[]_Boolean", routing :"String_String[]_Boolean", preference :"String", [expandWildcards=open] :"String", fields :"String_String[]_Boolean",  analyzeWildcard :true, analyzer :"String", ignoreUnavailable :true, allowNoIndices :true, terminateAfter : 99999, lenient :true});
// " 35       16  "  
    client.updateByQuery( { body : {}, pipeline :"String", requestsPerSecond : 99999, q :"String", [defaultOperator=OR] :"String", df :"String", waitForActiveShards :"String", [waitForCompletion=true] :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean", routing :"String_String[]_Boolean", searchType :"String", preference :"String", [expandWildcards=open] :"String", _source :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", version :true, versionType :true, [timeout=1m] :"2019-01-01", refresh :true, analyzeWildcard :true, analyzer :"String", ignoreUnavailable :true, allowNoIndices :true, terminateAfter : 99999, lenient :true, size : 99999, from : 99999, stats :"String_String[]_Boolean", requestCache :true, sort :"String_String[]_Boolean", scroll :"2019-01-01", searchTimeout :"2019-01-01", scrollSize : 99999, [slices=1] : 99999, [conflicts=abort] :"String"});
// " 6        17  "  
    client.deleteByQuery( { body : {}, requestsPerSecond : 99999, q :"String", [defaultOperator=OR] :"String", df :"String", waitForActiveShards :"String", [waitForCompletion=true] :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean", routing :"String_String[]_Boolean", searchType :"String", preference :"String", [expandWildcards=open] :"String", _source :"String_String[]_Boolean", _sourceExclude :"String_String[]_Boolean", _sourceInclude :"String_String[]_Boolean", version :true, [timeout=1m] :"2019-01-01", refresh :true, analyzeWildcard :true, analyzer :"String", ignoreUnavailable :true, allowNoIndices :true, terminateAfter : 99999, lenient :true, size : 99999, from : 99999, stats :"String_String[]_Boolean", requestCache :true, sort :"String_String[]_Boolean", scroll :"2019-01-01", searchTimeout :"2019-01-01", scrollSize : 99999, [slices=1] : 99999, [conflicts=abort] :"String"});
// " 36       18  "  
    client.updateByQueryRethrottle( { body : {},   _sourceExclude :"String_String[]_Boolean"});
// " 7        19  "  
    client.deleteByQueryRethrottle( { body : {}, taskId :"String", requestsPerSecond : 99999});
// " 19       20  "  
    client.msearch( { body : "JSONLines",  typedKeys :true, [preFilterShardSize=128] : 99999,  [maxConcurrentShardRequests=The default grows with the number of nodes in the cluster but is at most 256.] : 99999, index :"String_String[]_Boolean", type :"String_String[]_Boolean", searchType :"String", preference :"String"});
// " 29       21  "  
    client.scroll( { body : {}, scrollId :"String", scroll :"2019-01-01"});
// " 2        22  "  
    client.clearScroll( { body : {}, scrollId :"String_String[]_Boolean"});
// " 25       23  "  
    client.reindex( { body : {}, [slices=1] : 99999, requestsPerSecond : 99999,  waitForActiveShards :"String", [waitForCompletion=true] :true, refresh :true,  allowNoIndices :true   });
// " 26       24  "  
    client.reindexRethrottle( { body : {}, taskId :"String", requestsPerSecond : 99999,                 [timeout=1m] :"2019-01-01"});
// " 28       25  "  
    client.scriptsPainlessExecute( { body : {}});
// " 31       26  "  
    client.searchShards( { body : {},  index :"String_String[]_Boolean", local :true,  preference :"String", [expandWildcards=open] :"String", _source :"String_String[]_Boolean",    ignoreUnavailable :true, allowNoIndices :true    });
// " 14       27  "  
    client.getScript( { id :"String", masterTimeout :"2019-01-01"});
// " 23       28  "  
    client.putScript( { body : {}, context :"String", id :"String", timeout :"2019-01-01"});
// " 8        29  "  
    client.deleteScript( { body : {}, id :"String", masterTimeout :"2019-01-01", timeout :"2019-01-01"});
// " 24       30  "  
    client.rankEval( { body : {},  index :"String_String[]_Boolean", routing :"String",  [expandWildcards=open] :"String", masterTimeout :"2019-01-01", ignoreUnavailable :true});
// " 32       31  "  
    client.searchTemplate( { body : {}, typedKeys :true, explain :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean", routing :"String_String[]_Boolean", searchType :"String", preference :"String", [expandWildcards=open] :"String", profile :true, scroll :"2019-01-01", ignoreUnavailable :true});
// " 20       32  "  
    client.msearchTemplate( { body : "JSONLines",   index :"String_String[]_Boolean", type :"String_String[]_Boolean", searchType :"String", maxConcurrentSearches : 99999});
// " 27       33  "  
    client.renderSearchTemplate( { id :"String"});
// " 22       34  "  
    client.ping( "省略");
// " 17       35  "  
    client.info( ”省略");
// " 12       36  "  
    client.fieldCaps( { body : {},  index :"String_String[]_Boolean", [expandWildcards=open] :"String", fields :"String_String[]_Boolean", ignoreUnavailable :true, allowNoIndices :true });
// " 42       37  "  
    client.cat.help( { local :true,  help :true,  [ts=true] :true});
// " 37       38  "  
    client.cat.aliases( { format :"String",  masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true,  name :"String_String[]_Boolean"});
// " 38       39  "  
    client.cat.allocation( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, nodeId :"String_String[]_Boolean"});
// " 39       40  "  
    client.cat.count( { format :"String", bytes :"String", masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, index :"String_String[]_Boolean"});
// " 40       41  "  
    client.cat.fielddata( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, fields :"String_String[]_Boolean"});
// " 41       42  "  
    client.cat.health( { format :"String", bytes :"String", masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 43       43  "  
    client.cat.indices( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, index :"String_String[]_Boolean", health :"String", pri :true   });
// " 44       44  "  
    client.cat.master( { format :"String", bytes :"String", masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 45       45  "  
    client.cat.nodeattrs( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 46       46  "  
    client.cat.nodes( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 47       47  "  
    client.cat.pendingTasks( { format :"String",  masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, fullId :true});
// " 48       48  "  
    client.cat.plugins( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 49       49  "  
    client.cat.recovery( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, index :"String_String[]_Boolean"});
// " 50       50  "  
    client.cat.repositories( { format :"String", bytes :"String", masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true});
// " 51       51  "  
    client.cat.segments( { format :"String", local :true, h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, index :"String_String[]_Boolean"});
// " 52       52  "  
    client.cat.shards( { format :"String", bytes :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, index :"String_String[]_Boolean"});
// " 53       53  "  
    client.cat.snapshots( { format :"String", bytes :"String", masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, repository :"String_String[]_Boolean"});
// " 54       54  "  
    client.cat.tasks( { format :"String",  h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, actions :"String_String[]_Boolean", parentTask : 99999, ignoreUnavailable :true, detailed :true});
// " 55       55  "  
    client.cat.templates( { format :"String",  masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, name :"String", nodeId :"String_String[]_Boolean"});
// " 56       56  "  
    client.cat.threadPool( { format :"String", local :true, masterTimeout :"2019-01-01", h :"String_String[]_Boolean", help :true, s :"String_String[]_Boolean", v :true, threadPoolPatterns :"String_String[]_Boolean"});
// " 57       57  "  
    client.cluster.allocationExplain( { includeYesDecisions :true, size :"String",     body : {}});
// " 58       58  "  
    client.cluster.getSettings( { flatSettings :true, includeDiskInfo :true, timeout :"2019-01-01", includeDefaults :true});
// " 59       59  "  
    client.cluster.health( { [level=cluster] :"String", masterTimeout :"2019-01-01", masterTimeout :"2019-01-01", timeout :"2019-01-01", waitForActiveShards :"String", waitForNodes :"String", waitForEvents :"String", waitForNoRelocatingShards :true, waitForNoInitializingShards :true, waitForStatus :"String", index :"String_String[]_Boolean"});
// " 60       60  "  
    client.cluster.pendingTasks(  { local :true});
// " 61       61  "  
    client.cluster.putSettings( { flatSettings :true, masterTimeout :"2019-01-01", timeout :"2019-01-01",   body : {}});
// " 62       62  "  
    client.cluster.remoteInfo(  { masterTimeout :"2019-01-01"});
// " 63       63  "  
    client.cluster.reroute( { dryRun :true, retryFailed :true, metric :"String_String[]_Boolean", masterTimeout :"2019-01-01", timeout :"2019-01-01",   body : {}});
// " 64       64  "  
    client.cluster.state( { local :true, explain :true, flatSettings :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", index :"String_String[]_Boolean", metric :"String_String[]_Boolean"});
// " 65       65  "  
    client.cluster.stats( { flatSettings :true, masterTimeout :"2019-01-01", nodeId :"String_String[]_Boolean"});
// " 66       66  "  
    client.indices.analyze(  { timeout :"2019-01-01", index :"String",           body : {}    });
// " 67       67  "  
    client.indices.clearCache( { fieldData :true, fields :"String_String[]_Boolean", query :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean", requestCache :true, request :true,    body : {}    });
// " 68       68  "  
    client.indices.close(  { fielddata :true, timeout :"2019-01-01", masterTimeout :"2019-01-01", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean",           body : {}    });
// " 69       69  "  
    client.indices.create( { waitForActiveShards :"String", timeout :"2019-01-01", masterTimeout :"2019-01-01", updateAllTypes :true,  index :"String",           body : {}    });
// " 70       70  "  
    client.indices.delete( { timeout :"2019-01-01", masterTimeout :"2019-01-01", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean",           body : {}    });
// " 71       71  "  
    client.indices.deleteAlias( { timeout :"2019-01-01", masterTimeout :"2019-01-01",  index :"String_String[]_Boolean", name :"String_String[]_Boolean",      body : {}    });
// " 72       72  "  
    client.indices.deleteTemplate( { timeout :"2019-01-01", masterTimeout :"2019-01-01",    name :"String",       body : {}    });
// " 73       73  "  
    client.indices.exists( {  local :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", flatSettings :true, includeDefaults :true, index :"String_String[]_Boolean",          body : {}    });
// " 74       74  "  
    client.indices.existsAlias( {     ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=all] :"String", local :true, index :"String_String[]_Boolean", name :"String_String[]_Boolean",        body : {}    });
// " 75       75  "  
    client.indices.existsTemplate( { flatSettings :true,  masterTimeout :"2019-01-01", local :true,  name :"String_String[]_Boolean",      body : {}    });
// " 76       76  "  
    client.indices.existsType( {      ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", local :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean",       body : {}    });
// " 77       77  "  
    client.indices.flush( { force :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean",          body : {}    });
// " 78       78  "  
    client.indices.flushSynced(  { waitIfOngoing :true,  ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean",            body : {}    });
// " 79       79  "  
    client.indices.forcemerge( { flush :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", maxNumSegments : 99999, onlyExpungeDeletes :true, index :"String_String[]_Boolean",             body : {}    });
// " 80       80  "  
    client.indices.get( {  local :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", flatSettings :true, includeDefaults :true, masterTimeout :"2019-01-01", index :"String_String[]_Boolean",             body : {}    });
// " 81       81  "  
    client.indices.getAlias( {    ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=all] :"String", local :true, index :"String_String[]_Boolean", name :"String_String[]_Boolean"});
// " 82       82  "  
    client.indices.getFieldMapping( { includeDefaults :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", local :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean", fields :"String_String[]_Boolean"});
// " 83       83  "  
    client.indices.getMapping( {      ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", masterTimeout :"2019-01-01", local :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean"});
// " 84       84  "  
    client.indices.getSettings( {  masterTimeout :"2019-01-01", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open,closed] :"String", flatSettings :true, local :true, includeDefaults :true, index :"String_String[]_Boolean", name :"String_String[]_Boolean"});
// " 85       85  "  
    client.indices.getTemplate( { flatSettings :true,  masterTimeout :"2019-01-01", local :true,  name :"String_String[]_Boolean"});
// " 86       86  "  
    client.indices.getUpgrade( {      ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean"});
// " 87       87  "  
    client.indices.open( { timeout :"2019-01-01", masterTimeout :"2019-01-01", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=closed] :"String", waitForActiveShards :"String",  index :"String_String[]_Boolean"});
// " 88       88  "  
    client.indices.putAlias( { timeout :"2019-01-01", masterTimeout :"2019-01-01",  index :"String_String[]_Boolean", name :"String",      body : {}    });
// " 89       89  "  
    client.indices.putMapping( { timeout :"2019-01-01", masterTimeout :"2019-01-01", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", updateAllTypes :true,  index :"String_String[]_Boolean", type :"String",       body : {}    });
// " 90       90  "  
    client.indices.putSettings( { timeout :"2019-01-01", preserveExisting :true, ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", flatSettings :true,  index :"String_String[]_Boolean",          body : {}    });
// " 91       91  "  
    client.indices.putTemplate( { order : 99999, masterTimeout :"2019-01-01", timeout :"2019-01-01", masterTimeout :"2019-01-01", flatSettings :true,  name :"String",        body : {}    });
// " 92       92  "  
    client.indices.recovery( { detailed :true, create :true, index :"String_String[]_Boolean",            body : {}    });
// " 93       93  "  
    client.indices.refresh(  { activeOnly :true,  ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean"});
// " 94       94  "  
    client.indices.rollover( { timeout :"2019-01-01",  masterTimeout :"2019-01-01", waitForActiveShards :"String", alias :"String", newIndex :"String"});
// " 95       95  "  
    client.indices.segments(  { dryRun :true,  ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String", verbose :true,  index :"String_String[]_Boolean",          body : {}    });
// " 96       96  "  
    client.indices.shardStores( { status :"String_String[]_Boolean", ignoreUnavailable :true, allowNoIndices :true, [expandWildcards=open] :"String",  index :"String_String[]_Boolean"});
// " 97       97  "  
    client.indices.shrink( { copySettings :true, timeout :"2019-01-01", masterTimeout :"2019-01-01", waitForActiveShards :"String",  index :"String", target :"String",        body : {}    });
// " 98       98  "  
    client.indices.split( { copySettings :true, timeout :"2019-01-01", masterTimeout :"2019-01-01", waitForActiveShards :"String",  index :"String", target :"String",         body : {}    });
// " 99       99  "  
    client.indices.stats( { completionFields :"String_String[]_Boolean", fields :"String_String[]_Boolean", groups :"String_String[]_Boolean", [level=indices] :"String", types :"String_String[]_Boolean", includeSegmentFileSizes :true, index :"String_String[]_Boolean", metric :"String_String[]_Boolean",        body : {}    });
// " 100      100 "  
    client.indices.updateAliases(  { fielddataFields :"String_String[]_Boolean", timeout :"2019-01-01", masterTimeout :"2019-01-01"});
// " 101      101 "  
    client.indices.upgrade( { allowNoIndices :true, [expandWildcards=open] :"String", ignoreUnavailable :true, waitForCompletion :true, onlyAncientSegments :true, index :"String_String[]_Boolean",           body : {}    });
// " 102      102 "  
    client.indices.validateQuery( { explain :true, allowNoIndices :true, [expandWildcards=open] :"String", q :"String", analyzer :"String", analyzeWildcard :true, [defaultOperator=OR] :"String", df :"String", lenient :true, rewrite :true, allShards :true, index :"String_String[]_Boolean", type :"String_String[]_Boolean",      body : {}    });
// " 103      103 "  
    client.ingest.deletePipeline( { masterTimeout :"2019-01-01", ignoreUnavailable :true, id :"String",     body : {}});
// " 104      104 "  
    client.ingest.getPipeline( { masterTimeout :"2019-01-01", timeout :"2019-01-01", id :"String"});
// " 105      105 "  
    client.ingest.processorGrok( "省略");
// " 106      106 "  
    client.ingest.putPipeline( { masterTimeout :"2019-01-01", id :"String",  body : {}});
// " 107      107 "  
    client.ingest.simulate( { verbose :true, timeout :"2019-01-01", id :"String",   body : {}});
// " 108      108 "  
    client.nodes.hotThreads( { interval :"2019-01-01", threads : 99999, ignoreIdleThreads :true, type :"String", timeout :"2019-01-01", nodeId :"String_String[]_Boolean"});
// " 109      109 "  
    client.nodes.info( { flatSettings :true, snapshots : 99999, timeout :"2019-01-01", nodeId :"String_String[]_Boolean", metric :"String_String[]_Boolean"});
// " 110      110 "  
    client.nodes.reloadSecureSettings( {  nodeId :"String_String[]_Boolean",    body : {}});
// " 111      111 "  
    client.nodes.stats( { completionFields :"String_String[]_Boolean", fields :"String_String[]_Boolean", groups :true, [level=node] :"String", types :"String_String[]_Boolean", timeout :"2019-01-01", includeSegmentFileSizes :true, metric :"String_String[]_Boolean", indexMetric :"String_String[]_Boolean", nodeId :"String_String[]_Boolean"});
// " 112      112 "  
    client.nodes.usage(  { fielddataFields :"String_String[]_Boolean", metric :"String_String[]_Boolean", nodeId :"String_String[]_Boolean"});
// " 113      113 "  
    client.snapshot.create( { masterTimeout :"2019-01-01",  repository :"String", snapshot :"String",               body : {}});
// " 114      114 "  
    client.snapshot.createRepository( { masterTimeout :"2019-01-01", waitForCompletion :true, verify :true, repository :"String", body : {}});
// " 115      115 "  
    client.snapshot.delete( { masterTimeout :"2019-01-01", timeout :"2019-01-01", repository :"String", snapshot :"String",              body : {}});
// " 116      116 "  
    client.snapshot.deleteRepository( { masterTimeout :"2019-01-01",  repository :"String_String[]_Boolean", body : {}});
// " 117      117 "  
    client.snapshot.get( { masterTimeout :"2019-01-01", timeout :"2019-01-01", verbose :true, repository :"String", snapshot :"String_String[]_Boolean"});
// " 118      118 "  
    client.snapshot.getRepository( { masterTimeout :"2019-01-01", ignoreUnavailable :true, repository :"String_String[]_Boolean"});
// " 119      119 "  
    client.snapshot.restore( { masterTimeout :"2019-01-01", local :true, repository :"String", snapshot :"String",               body : {}});
// " 120      120 "  
    client.snapshot.status( { masterTimeout :"2019-01-01", waitForCompletion :true, repository :"String", snapshot :"String_String[]_Boolean"});
// " 121      121 "  
    client.snapshot.verifyRepository( { masterTimeout :"2019-01-01", ignoreUnavailable :true, repository :"String", body : {}});
// " 122      122 "  
    client.tasks.cancel( { nodes :"String_String[]_Boolean", timeout :"2019-01-01",  parentTaskId :"String", taskId :"String",       body : {}});
// " 123      123 "  
    client.tasks.get(  { actions :"String_String[]_Boolean", taskId :"String"});
// " 124      124 "  
    client.tasks.list( { nodes :"String_String[]_Boolean", timeout :"2019-01-01", detailed :true,  parentTaskId :"String", waitForCompletion :true, [groupBy=nodes] :"String", timeout :"2019-01-01"});









まとめた割にはコピペビリティも一覧性も高くない...

table版

他のものは、オレオレ視点で並び替えや編集を加えていますが、これは公式の並び順に合わせています。 (コピペミスなどで抜け等あるかもしれませんが。)

無印

項番 グループ API ひとこと概要 引数 引数の項目名と型
1 トップ bulk 公式 ”バルク”のAPI [params, [callback]] ◆ waitForActiveShards ◇String  ◆refresh ◇String  ◆routing ◇String  ◆timeout ◇DurationString  ◆type ◇String  ◆fields ◇String,String,Boolean  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆pipeline ◇String  ◆index ◇String  ◆body ◇Object  ◆JSONLines 
2 トップ clearScroll 公式 scroll検索のクリア [params, [callback]] ◆ scrollId ◇String,String,Boolean  ◆body ◇Object  ,JSON 
3 トップ count 公式 件数カウント [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆minScore ◇Number  ◆preference ◇String  ◆routing ◇String,String,Boolean  ◆q ◇String  ◆analyzer ◇String  ◆analyzeWildcard ◇Boolean  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆lenient ◇Boolean  ◆terminateAfter ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
4 トップ create 公式 create全般 [params, [callback]] ◆ waitForActiveShards ◇String  ◆parent ◇String  ◆refresh ◇String  ◆routing ◇String  ◆timeout ◇DurationString  ◆version ◇Number  ◆versionType ◇String  ◆pipeline ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
5 トップ delete 公式 削除 by id [params, [callback]] ◆ waitForActiveShards ◇String  ◆parent ◇String  ◆refresh ◇String  ◆routing ◇String  ◆timeout ◇DurationString  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
6 トップ deleteByQuery 公式 deleteByQuery [params, [callback]] ◆ analyzer ◇String  ◆analyzeWildcard ◇Boolean  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆from ◇Number  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[conflicts=abort] ◇String  ◆[expandWildcards=open] ◇String  ◆lenient ◇Boolean  ◆preference ◇String  ◆q ◇String  ◆routing ◇String,String,Boolean  ◆scroll ◇DurationString  ◆searchType ◇String  ◆searchTimeout ◇DurationString  ◆size ◇Number 
公式 ◆sort ◇String,String,Boolean  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆terminateAfter ◇Number  ◆stats ◇String,String,Boolean  ◆version ◇Boolean  ◆requestCache ◇Boolean  ◆refresh ◇Boolean  ◆[timeout=1m] ◇DurationString  ◆waitForActiveShards ◇String  ◆scrollSize ◇Number  ◆[waitForCompletion=true] ◇Boolean  ◆requestsPerSecond ◇Number  ◆[slices=1] ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
7 トップ deleteByQueryRethrottle 公式 deleteByQueryリスロットル [params, [callback]] ◆ requestsPerSecond ◇Number  ◆taskId ◇String  ◆body ◇Object  ,JSON 
8 トップ deleteScript 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆id ◇String  ◆body ◇Object  ,JSON 
9 トップ exists 公式 [params, [callback]] ◆ storedFields ◇String,String,Boolean  ◆parent ◇String  ◆preference ◇String  ◆realtime ◇Boolean  ◆refresh ◇Boolean  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
10 トップ existsSource 公式 [params, [callback]] ◆ parent ◇String  ◆preference ◇String  ◆realtime ◇Boolean  ◆refresh ◇Boolean  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
11 トップ explain 公式 [params, [callback]] ◆ analyzeWildcard ◇Boolean  ◆analyzer ◇String  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆storedFields ◇String,String,Boolean  ◆lenient ◇Boolean  ◆parent ◇String  ◆preference ◇String  ◆q ◇String  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
12 トップ fieldCaps 公式 fieldCapsを確認 [params, [callback]] ◆ fields ◇String,String,Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
13 トップ get 公式 JSONドキュメントを取得 by id [params, [callback]] ◆ storedFields ◇String,String,Boolean  ◆parent ◇String  ◆preference ◇String  ◆realtime ◇Boolean  ◆refresh ◇Boolean  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String 
14 トップ getScript 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆id ◇String  ◆
15 トップ getSource 公式 sourceのみ取得by id [params, [callback]] ◆ parent ◇String  ◆preference ◇String  ◆realtime ◇Boolean  ◆refresh ◇Boolean  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String 
16 トップ index 公式 CRUD全部 [params, [callback]] ◆ ◆waitForActiveShards ◇String  ◆[opType=index] ◇String  ◆parent ◇String  ◆refresh ◇String  ◆routing ◇String  ◆timeout ◇DurationString  ◆version ◇Number  ◆versionType ◇String  ◆pipeline ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
17 トップ info 公式 クラスターのbasic infoを取得 [params, [callback]]
18 トップ mget 公式 mult系 [params, [callback]] ◆ storedFields ◇String,String,Boolean  ◆preference ◇String  ◆realtime ◇Boolean  ◆refresh ◇Boolean  ◆routing ◇String  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
19 トップ msearch 公式 mult系 [params, [callback]] ◆ searchType ◇String  ◆maxConcurrentSearches ◇Number  ◆typedKeys ◇Boolean  ◆[preFilterShardSize=128] ◇Number  ◆[maxConcurrentShardRequests=The default grows with the number of nodes in the cluster but is at most 256.] ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ◆JSONLines 
20 トップ msearchTemplate 公式 mult系 [params, [callback]] ◆ searchType ◇String  ◆typedKeys ◇Boolean  ◆maxConcurrentSearches ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ◆JSONLines 
21 トップ mtermvectors 公式 [params, [callback]] ◆ ids ◇String,String,Boolean  ◆termStatistics ◇Boolean  ◆[fieldStatistics=true] ◇Boolean  ◆fields ◇String,String,Boolean  ◆[offsets=true] ◇Boolean  ◆[positions=true] ◇Boolean  ◆[payloads=true] ◇Boolean  ◆preference ◇String  ◆routing ◇String  ◆parent ◇String  ◆realtime ◇Boolean  ◆version ◇Number  ◆versionType ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
22 トップ ping 公式 [params, [callback]]
23 トップ putScript 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆context ◇String  ◆id ◇String  ◆body ◇Object  ,JSON 
24 トップ rankEval 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
25 トップ reindex 公式 [params, [callback]] ◆ refresh ◇Boolean  ◆[timeout=1m] ◇DurationString  ◆waitForActiveShards ◇String  ◆[waitForCompletion=true] ◇Boolean  ◆requestsPerSecond ◇Number  ◆[slices=1] ◇Number  ◆body ◇Object  ,JSON 
26 トップ reindexRethrottle 公式 [params, [callback]] ◆ requestsPerSecond ◇Number  ◆taskId ◇String  ◆body ◇Object  ,JSON 
27 トップ renderSearchTemplate 公式 [params, [callback]] ◆ id ◇String  ◆body ◇Object  ,JSON 
28 トップ scriptsPainlessExecute 公式 [params, [callback]]
29 トップ scroll 公式 scroll検索 [params, [callback]] ◆ scroll ◇DurationString  ◆scrollId ◇String  ◆body ◇Object  ,JSON 
30 トップ search 公式 search [params, [callback]] ◆ analyzer ◇String  ◆analyzeWildcard ◇Boolean  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆explain ◇Boolean  ◆storedFields ◇String,String,Boolean  ◆docvalueFields ◇String,String,Boolean  ◆from ◇Number  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆lenient ◇Boolean  ◆preference ◇String  ◆q ◇String  ◆routing ◇String,String,Boolean  ◆scroll ◇DurationString  ◆searchType ◇String  ◆size ◇Number 
公式 ◆sort ◇String,String,Boolean  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆terminateAfter ◇Number  ◆stats ◇String,String,Boolean  ◆suggestField ◇String  ◆[suggestMode=missing] ◇String  ◆suggestSize ◇Number  ◆suggestText ◇String  ◆timeout ◇DurationString  ◆trackScores ◇Boolean  ◆trackTotalHits ◇Boolean  ◆[allowPartialSearchResults=true] ◇Boolean  ◆typedKeys ◇Boolean  ◆version ◇Boolean  ◆requestCache ◇Boolean  ◆[batchedReduceSize=512] ◇Number  ◆[maxConcurrentShardRequests=The default grows with the number of nodes in the cluster but is at most 256.] ◇Number  ◆[preFilterShardSize=128] ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
31 トップ searchShards 公式 [params, [callback]] ◆ preference ◇String  ◆routing ◇String  ◆local ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
32 トップ searchTemplate 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆preference ◇String  ◆routing ◇String,String,Boolean  ◆scroll ◇DurationString  ◆searchType ◇String  ◆explain ◇Boolean  ◆profile ◇Boolean  ◆typedKeys ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
33 トップ termvectors 公式 [params, [callback]] ◆ termStatistics ◇Boolean  ◆[fieldStatistics=true] ◇Boolean  ◆fields ◇String,String,Boolean  ◆[offsets=true] ◇Boolean  ◆[positions=true] ◇Boolean  ◆[payloads=true] ◇Boolean  ◆preference ◇String  ◆routing ◇String  ◆parent ◇String  ◆realtime ◇Boolean  ◆version ◇Number  ◆versionType ◇String  ◆index ◇String  ◆type ◇String  ◆id ◇String  ◆body ◇Object  ,JSON 
34 トップ update 公式 update(script利用可能) [params, [callback]] ◆ waitForActiveShards ◇String  ◆fields ◇String,String,Boolean  ◆source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆lang ◇String  ◆parent ◇String  ◆refresh ◇String  ◆retryOnConflict ◇Number  ◆routing ◇String  ◆timeout ◇DurationString  ◆version ◇Number  ◆versionType ◇String  ◆id ◇String  ◆index ◇String  ◆type ◇String  ◆body ◇Object  ,JSON 
35 トップ updateByQuery 公式 updateByQuery [params, [callback]] ◆ analyzer ◇String  ◆analyzeWildcard ◇Boolean  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆from ◇Number  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[conflicts=abort] ◇String  ◆[expandWildcards=open] ◇String  ◆lenient ◇Boolean  ◆pipeline ◇String  ◆preference ◇String  ◆q ◇String  ◆routing ◇String,String,Boolean  ◆scroll ◇DurationString  ◆searchType ◇String  ◆searchTimeout ◇DurationString  ◆size ◇Number  ◆sort ◇String,String,Boolean 
公式 source ◇String,String,Boolean  ◆sourceExclude ◇String,String,Boolean  ◆_sourceInclude ◇String,String,Boolean  ◆terminateAfter ◇Number  ◆stats ◇String,String,Boolean  ◆version ◇Boolean  ◆versionType ◇Boolean  ◆requestCache ◇Boolean  ◆refresh ◇Boolean  ◆[timeout=1m] ◇DurationString  ◆waitForActiveShards ◇String  ◆scrollSize ◇Number  ◆[waitForCompletion=true] ◇Boolean  ◆requestsPerSecond ◇Number  ◆[slices=1] ◇Number  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
36 トップ updateByQueryRethrottle 公式 updateByQueryリスロットル [params, [callback]] ◆ requestsPerSecond ◇Number  ◆taskId ◇String  ◆body ◇Object  ,JSON 

cat、cluster, indices

項番 グループ API ひとこと概要 引数 引数の項目名と型
37 cat aliases 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆name ◇String,String,Boolean 
38 cat allocation 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆nodeId ◇String,String,Boolean 
39 cat count 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆index ◇String,String,Boolean 
40 cat fielddata 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆fields ◇String,String,Boolean 
41 cat health 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆[ts=true] ◇Boolean  ◆v ◇Boolean 
42 cat help 公式 [params, [callback]] ◆ help ◇Boolean  ◆s ◇String,String,Boolean  ◆
43 cat indices 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆health ◇String  ◆help ◇Boolean  ◆pri ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆index ◇String,String,Boolean 
44 cat master 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
45 cat nodeattrs 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
46 cat nodes 公式 [params, [callback]] ◆ format ◇String  ◆fullId ◇Boolean  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
47 cat pendingTasks 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
48 cat plugins 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
49 cat recovery 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆index ◇String,String,Boolean 
50 cat repositories 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
51 cat segments 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆index ◇String,String,Boolean 
52 cat shards 公式 [params, [callback]] ◆ format ◇String  ◆bytes ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆index ◇String,String,Boolean 
53 cat snapshots 公式 [params, [callback]] ◆ format ◇String  ◆ignoreUnavailable ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆repository ◇String,String,Boolean 
54 cat tasks 公式 [params, [callback]] ◆ format ◇String  ◆nodeId ◇String,String,Boolean  ◆actions ◇String,String,Boolean  ◆detailed ◇Boolean  ◆parentTask ◇Number  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean 
55 cat templates 公式 [params, [callback]] ◆ format ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆name ◇String 
56 cat threadPool 公式 [params, [callback]] ◆ format ◇String  ◆size ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆h ◇String,String,Boolean  ◆help ◇Boolean  ◆s ◇String,String,Boolean  ◆v ◇Boolean  ◆threadPoolPatterns ◇String,String,Boolean 
57 cluster allocationExplain 公式 [params, [callback]] ◆ includeYesDecisions ◇Boolean  ◆includeDiskInfo ◇Boolean  ◆body ◇Object  ,JSON 
58 cluster getSettings 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆includeDefaults ◇Boolean 
59 cluster health 公式 [params, [callback]] ◆ [level=cluster] ◇String  ◆local ◇Boolean  ◆masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆waitForActiveShards ◇String  ◆waitForNodes ◇String  ◆waitForEvents ◇String  ◆waitForNoRelocatingShards ◇Boolean  ◆waitForNoInitializingShards ◇Boolean  ◆waitForStatus ◇String  ◆index ◇String,String,Boolean 
60 cluster pendingTasks 公式 [params, [callback]] ◆ local ◇Boolean  ◆masterTimeout ◇DurationString 
61 cluster putSettings 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆body ◇Object  ,JSON 
62 cluster remoteInfo 公式 [params, [callback]]
63 cluster reroute 公式 [params, [callback]] ◆ dryRun ◇Boolean  ◆explain ◇Boolean  ◆retryFailed ◇Boolean  ◆metric ◇String,String,Boolean  ◆masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆body ◇Object  ,JSON 
64 cluster state 公式 [params, [callback]] ◆ local ◇Boolean  ◆masterTimeout ◇DurationString  ◆flatSettings ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆metric ◇String,String,Boolean 
65 cluster stats 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆timeout ◇DurationString  ◆nodeId ◇String,String,Boolean 
66 indices analyze 公式 [params, [callback]] ◆ index ◇String  ◆body ◇Object  ,JSON 
67 indices clearCache 公式 [params, [callback]] ◆ fieldData ◇Boolean  ◆fielddata ◇Boolean  ◆fields ◇String,String,Boolean  ◆query ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆requestCache ◇Boolean  ◆request ◇Boolean  ◆body ◇Object  ,JSON 
68 indices close 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
69 indices create 公式 [params, [callback]] ◆ waitForActiveShards ◇String  ◆timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆updateAllTypes ◇Boolean  ◆index ◇String  ◆body ◇Object  ,JSON 
70 indices delete 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
71 indices deleteAlias 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆index ◇String,String,Boolean  ◆name ◇String,String,Boolean  ◆body ◇Object  ,JSON 
72 indices deleteTemplate 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆name ◇String  ◆body ◇Object  ,JSON 
73 indices exists 公式 [params, [callback]] ◆ local ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆flatSettings ◇Boolean  ◆includeDefaults ◇Boolean  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
74 indices existsAlias 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=all] ◇String  ◆local ◇Boolean  ◆index ◇String,String,Boolean  ◆name ◇String,String,Boolean  ◆body ◇Object  ,JSON 
75 indices existsTemplate 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆masterTimeout ◇DurationString  ◆local ◇Boolean  ◆name ◇String,String,Boolean  ◆body ◇Object  ,JSON 
76 indices existsType 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆local ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 
77 indices flush 公式 [params, [callback]] ◆ force ◇Boolean  ◆waitIfOngoing ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
78 indices flushSynced 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
79 indices forcemerge 公式 [params, [callback]] ◆ flush ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆maxNumSegments ◇Number  ◆onlyExpungeDeletes ◇Boolean  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
80 indices get 公式 [params, [callback]] ◆ local ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆flatSettings ◇Boolean  ◆includeDefaults ◇Boolean  ◆masterTimeout ◇DurationString  ◆index ◇String,String,Boolean 
81 indices getAlias 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=all] ◇String  ◆local ◇Boolean  ◆index ◇String,String,Boolean  ◆name ◇String,String,Boolean  ◆
82 indices getFieldMapping 公式 [params, [callback]] ◆ includeDefaults ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆local ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆fields ◇String,String,Boolean 
83 indices getMapping 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆masterTimeout ◇DurationString  ◆local ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆
84 indices getSettings 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open,closed] ◇String  ◆flatSettings ◇Boolean  ◆local ◇Boolean  ◆includeDefaults ◇Boolean  ◆index ◇String,String,Boolean  ◆name ◇String,String,Boolean 
85 indices getTemplate 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆masterTimeout ◇DurationString  ◆local ◇Boolean  ◆name ◇String,String,Boolean 
86 indices getUpgrade 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean 
87 indices open 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=closed] ◇String  ◆waitForActiveShards ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
88 indices putAlias 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆index ◇String,String,Boolean  ◆name ◇String  ◆body ◇Object  ,JSON 
89 indices putMapping 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆updateAllTypes ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String  ◆body ◇Object  ,JSON 
90 indices putSettings 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆preserveExisting ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆flatSettings ◇Boolean  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
91 indices putTemplate 公式 [params, [callback]] ◆ order ◇Number  ◆create ◇Boolean  ◆timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆flatSettings ◇Boolean  ◆name ◇String  ◆body ◇Object  ,JSON 
92 indices recovery 公式 [params, [callback]] ◆ detailed ◇Boolean  ◆activeOnly ◇Boolean  ◆index ◇String,String,Boolean 
93 indices refresh 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
94 indices rollover 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆dryRun ◇Boolean  ◆masterTimeout ◇DurationString  ◆waitForActiveShards ◇String  ◆alias ◇String  ◆newIndex ◇String  ◆body ◇Object  ,JSON 
95 indices segments 公式 [params, [callback]] ◆ ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆verbose ◇Boolean  ◆index ◇String,String,Boolean  ◆
96 indices shardStores 公式 [params, [callback]] ◆ status ◇String,String,Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆index ◇String,String,Boolean  ◆
97 indices shrink 公式 [params, [callback]] ◆ copySettings ◇Boolean  ◆timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆waitForActiveShards ◇String  ◆index ◇String  ◆target ◇String  ◆body ◇Object  ,JSON 
98 indices split 公式 [params, [callback]] ◆ copySettings ◇Boolean  ◆timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆waitForActiveShards ◇String  ◆index ◇String  ◆target ◇String  ◆body ◇Object  ,JSON 
99 indices stats 公式 [params, [callback]] ◆ completionFields ◇String,String,Boolean  ◆fielddataFields ◇String,String,Boolean  ◆fields ◇String,String,Boolean  ◆groups ◇String,String,Boolean  ◆[level=indices] ◇String  ◆types ◇String,String,Boolean  ◆includeSegmentFileSizes ◇Boolean  ◆index ◇String,String,Boolean  ◆metric ◇String,String,Boolean 
100 indices updateAliases 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆masterTimeout ◇DurationString  ◆body ◇Object  ,JSON 
101 indices upgrade 公式 [params, [callback]] ◆ allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆ignoreUnavailable ◇Boolean  ◆waitForCompletion ◇Boolean  ◆onlyAncientSegments ◇Boolean  ◆index ◇String,String,Boolean  ◆body ◇Object  ,JSON 
102 indices validateQuery 公式 [params, [callback]] ◆ explain ◇Boolean  ◆ignoreUnavailable ◇Boolean  ◆allowNoIndices ◇Boolean  ◆[expandWildcards=open] ◇String  ◆q ◇String  ◆analyzer ◇String  ◆analyzeWildcard ◇Boolean  ◆[defaultOperator=OR] ◇String  ◆df ◇String  ◆lenient ◇Boolean  ◆rewrite ◇Boolean  ◆allShards ◇Boolean  ◆index ◇String,String,Boolean  ◆type ◇String,String,Boolean  ◆body ◇Object  ,JSON 

ingest, nodes, snapshot, tasks

項番 グループ API ひとこと概要 引数 引数の項目名と型
103 ingest deletePipeline 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆id ◇String  ◆body ◇Object  ,JSON 
104 ingest getPipeline 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆id ◇String 
105 ingest processorGrok 公式 [params, [callback]]
106 ingest putPipeline 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆id ◇String  ◆body ◇Object  ,JSON 
107 ingest simulate 公式 [params, [callback]] ◆ verbose ◇Boolean  ◆id ◇String  ◆body ◇Object  ,JSON 
108 nodes hotThreads 公式 [params, [callback]] ◆ interval ◇DurationString  ◆snapshots ◇Number  ◆threads ◇Number  ◆ignoreIdleThreads ◇Boolean  ◆type ◇String  ◆timeout ◇DurationString  ◆nodeId ◇String,String,Boolean 
109 nodes info 公式 [params, [callback]] ◆ flatSettings ◇Boolean  ◆timeout ◇DurationString  ◆nodeId ◇String,String,Boolean  ◆metric ◇String,String,Boolean 
110 nodes reloadSecureSettings 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆nodeId ◇String,String,Boolean  ◆body ◇Object  ,JSON 
111 nodes stats 公式 [params, [callback]] ◆ completionFields ◇String,String,Boolean  ◆fielddataFields ◇String,String,Boolean  ◆fields ◇String,String,Boolean  ◆groups ◇Boolean  ◆[level=node] ◇String  ◆types ◇String,String,Boolean  ◆timeout ◇DurationString  ◆includeSegmentFileSizes ◇Boolean  ◆metric ◇String,String,Boolean  ◆indexMetric ◇String,String,Boolean  ◆nodeId ◇String,String,Boolean 
112 nodes usage 公式 [params, [callback]] ◆ timeout ◇DurationString  ◆metric ◇String,String,Boolean  ◆nodeId ◇String,String,Boolean  ◆
113 snapshot create 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆waitForCompletion ◇Boolean  ◆repository ◇String  ◆snapshot ◇String  ◆body ◇Object  ,JSON 
114 snapshot createRepository 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆verify ◇Boolean  ◆repository ◇String  ◆body ◇Object  ,JSON 
115 snapshot delete 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆repository ◇String  ◆snapshot ◇String  ◆body ◇Object  ,JSON 
116 snapshot deleteRepository 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆repository ◇String,String,Boolean  ◆body ◇Object  ,JSON 
117 snapshot get 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆verbose ◇Boolean  ◆repository ◇String  ◆snapshot ◇String,String,Boolean 
118 snapshot getRepository 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆local ◇Boolean  ◆repository ◇String,String,Boolean 
119 snapshot restore 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆waitForCompletion ◇Boolean  ◆repository ◇String  ◆snapshot ◇String  ◆body ◇Object  ,JSON 
120 snapshot status 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆ignoreUnavailable ◇Boolean  ◆repository ◇String  ◆snapshot ◇String,String,Boolean 
121 snapshot verifyRepository 公式 [params, [callback]] ◆ masterTimeout ◇DurationString  ◆timeout ◇DurationString  ◆repository ◇String  ◆body ◇Object  ,JSON 
122 tasks cancel 公式 [params, [callback]] ◆ nodes ◇String,String,Boolean  ◆actions ◇String,String,Boolean  ◆parentTaskId ◇String  ◆taskId ◇String  ◆body ◇Object  ,JSON 
123 tasks get 公式 [params, [callback]] ◆ waitForCompletion ◇Boolean  ◆timeout ◇DurationString  ◆taskId ◇String 
124 tasks list 公式 [params, [callback]] ◆ nodes ◇String,String,Boolean  ◆actions ◇String,String,Boolean  ◆detailed ◇Boolean  ◆parentTaskId ◇String  ◆waitForCompletion ◇Boolean  ◆[groupBy=nodes] ◇String  ◆timeout ◇DurationString