注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。
Phonograph への書き戻しは、Slate から Foundry オントロジーに変更を加えるために推奨されません。代わりに、Action Widget を使用して Ontology に更新と変更を適用するための Actions を使用することを推奨します。詳細は Action types documentation を参照してください。
このガイドは、Actions を設定してオントロジーにカスタムまたは複雑な変更を加えることができないユーザー向けに作成されました。Phonograph への書き戻しを進行する前に、Palantir の担当者に連絡して、Actions が特定の使用ケースに適切に使用できるかどうかを確認してください。
Slate でユーザーの入力/データの変更をキャプチャして Foundry に保存するためには、以下の 3つのコンポーネントが必要です:
まず、Dataset タブで Slate アプリケーションにソースデータセットを追加します。+ Add ボタンを使用して、名前が asteroid_notes
というシンプルな派生データセットを追加します。この概念的なデータセットには、小惑星の名前と、小惑星に関するユーザー入力情報を保持するための空の行 research_notes
が含まれています。
データセットを追加した後、データセットの同期設定を表示します。手動編集キャッシュである Phonograph への同期を設定します。
プライマリーキー を選択します。プライマリーキーの選択は、単一の行を一意に識別しなければなりません。一般的には、適切なプライマリーキーを生成するために、トランスフォームで複数の行を組み合わせる必要があります。グループの行をジョイントプライマリーキーとして定義することも可能ですが、これはデータの編集の複雑さを増加させます。
プライマリーキーが設定されたら、Foundry でユーザーの編集を保存する書き戻しデータセットを作成します。"Browse" を選択して、編集内容を保存できる Foundry のデータセットを作成します。ポップアップウィンドウで、データセットの名前と、データセットを作成したい Foundry の場所を指定します。
終了したら、同期設定は次のようになります:
書き戻しインデックスは struct
行タイプをサポートしていません。これは、DateTime
行タイプを持つデータセットはインデックス化に失敗することを意味します。Contour または SQL または Python トランスフォームを使用して、DateTime
行をインデックス化する前に Timestamp
にキャストできます。
現在、UI を通じて同期を登録解除(削除)することはできません。ただし、Slate での使用には、"Table Registry - Unregister" エンドポイントにクエリを追加できます。唯一のパラメーターは Table RID で、結果は Table の削除 - これは入力または出力データセットに影響を与えません。関連するデータセットの同期 UI では、登録された書き戻し同期がないことがわかります。これは、Table のすべてのデータを永久に削除するので、慎重に使用し、クエリを削除するか、手動実行に設定します。
データが Phonograph にインデックス化されたので、今度はそれから読み取りと書き込みができます。最も単純なパターンは次のようになります:
後ほど、bulk
エンドポイントを使用して複雑さを追加し、フロントエンドの表示状態とバックエンドのデータ状態を分離して、より応答性の高いアプリケーションを維持するオプションを探る予定ですが、これらはいずれも高度なトピックです。
テーブルからすべての行を取得するには、新しい Slate クエリを作成する必要があります。
Table Search Service
を選択します。Search Request
フィールドを記入します。このリクエストは matchAll
ブロックを使用しており、すべての行を返します。テーブルの RID(同期設定で利用可能)と、ソートする行(オプション)を記入する必要があります。Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "tableRids": [ "<your_table_rid>" // あなたのテーブルRIDを入れてください ], "filter": { "type": "matchAll", // すべての条件に一致させる "matchAll": {} }, "sort": { "<your_column_to_sort_by>": { // 並び替える列を選択してください "order": "desc" // 降順で並び替え } } }
このクエリパターンでは、ページング(ブラウザのメモリ負荷を軽減し、パフォーマンスを向上させるため)と、sort
ブロックの追加による並べ替えが可能です。サーバーサイドページング機能の使用方法の詳細は、テーブルウィジェット をご覧ください。
"{{w_tableWidget.gridOptions.pagingOptions.currentOffset}}" # 現在のオフセット(表示開始位置)を指定するオプション
"{{w_phonographResults.gridOptions.pagingOptions.pageSize}}"
このコードは、AngularJSなどのフレームワークで使用される、データバインディングの一例です。具体的には、'w_phonographResults'オブジェクトの'gridOptions'プロパティ内にある'pagingOptions'プロパティの'pageSize'値を取得しています。
"{{w_phonographResults.gridOptions.pagingOptions.pageSize}}"
このコードは、AngularJSなどのフレームワークで使われる、データバインディングの一例です。具体的には、'w_phonographResults'オブジェクトの'gridOptions'プロパティ内の'pagingOptions'プロパティの'pageSize'値を取得しています。
以前は行の取得に推奨されていた Get All Rows
エンドポイントは廃止されました。上記のように Search
エンドポイントに移行し、f_getAllRowsFormat 関数を以下のように更新してください:
var rawData= {{getAllRows.result.[0].results.rows}}
は
var rawData= _.map({{getAllRows.result.[0].hits}}, h => h.row)
すべての行を一度に取得するだけでなく、Get Rows
エンドポイントを使用してプライマリキーのオブジェクトのリストを提供し、IDによる複数の行を取得することもできます。これはユーザーが新しい値を入力するときに行がすでに存在するかどうかを確認する簡単な方法であり、edit
または add
イベントを適用するかどうかを決定するために必要です(以下で詳しく説明します)。
これらのgetエンドポイントの結果はオブジェクトの配列であり、各オブジェクトは行を表し、ネストした primaryKey
オブジェクトと columns
オブジェクトの値はその行の行:値のペアを表します。Slateのウィジェット(チャートやテーブルなど)は、各配列が行を表し、配列のインデックスが指定の行の値となる並列配列のデータを期待しています。このヘルパー関数は、Get
または Search
からの結果を入力として取り、テーブルや他のウィジェットにフィードするための並列配列を返します:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// 変数 rawData には、全ての行が格納されます。 var rawData= _.map({{getAllRows.result.[0].hits}}, h => h.row) // 主キーとカラムを取得します。 var primaryKeys=Object.keys(rawData[0].primaryKey); var columns=Object.keys(rawData[0].columns); // パースされたデータを格納するためのオブジェクトを作成します。 var parsedData={} // 初期化 // 主キーとカラムに対して、空の配列を作成します。 for (var pkey of primaryKeys) { parsedData[pkey]=[] } for (var column of columns) { parsedData[column]=[] } // rawData の各行に対して、主キーとカラムの値を parsedData に追加します。 for (var row of rawData) { for (var pkey of primaryKeys) { parsedData[pkey].push(row.primaryKey[pkey]) } for (var column of columns) { parsedData[column].push(row.columns[column]) } } // 変換されたデータを返します。 return parsedData;
データ内の null 値は、Phonograph にインデックス化されません。その結果、null 値を含む行が Phonograph に存在しない場合があります。Phonograph の結果を行と行に変換する際には、これらの欠損値を考慮する必要があります。以下に、すべての行にわたるすべての行を検出する例を示します。この例は、最初の行の null 値に関する問題を避けるために、上記の例と組み合わせることができます。
Copied!1 2 3 4 5 6 7 8 9 10 11 12
// getAllRows.result.[0].hitsの結果をマップし、それぞれのrowの主キーとカラムを新しいオブジェクトに割り当てます const queryResult = {{getAllRows.result.[0].hits}}.map(e => (Object.assign({}, ...[e.row.primaryKey, e.row.columns]))); // queryResultのすべてのキーを取得し、重複を排除したカラムの配列を作成します const columns = [...new Set(...queryResult.map(e => Object.keys(e)))]; // 各カラムに対して、queryResultのすべてのエントリを取得し、そのカラムの値で新しいオブジェクトを作成します // これにより、各カラムがキーで、そのカラムのすべての値が配列として格納される新しいオブジェクトが作成されます const queryResultFilled = Object.assign({}, ...columns.map(e => ({[e]: queryResult.map(_e => _e[e])}))); // 作成したオブジェクトを返します return queryResultFilled;
検索サービスのエンドポイントは、関連する Phonograph テーブルの検索インデックスを使用します。この検索インデックスは、ストレージサービスの Post Event
エンドポイントと同期的に更新されないため、変更が書き込まれてから検索エンドポイントへのクエリに変更が表示されるまでにわずかな遅延が発生します。簡単なパターンとして、Toast ウィジェットを使用してタイマーを作成する方法があります。
q_postEvent.success
-> w_successToast.open
w_successToast
のタイムアウトを 5000
(5秒) に設定w_successToast.close
-> q_getAllRows
変更された行を取得できるように、トーストの長さを調整する必要があるかもしれません。また、getAllRows クエリに sort
ブロックを追加してください。デフォルトのソートは、行ドキュメントの最終更新タイムスタンプによるもので、編集された行がすべての結果の後ろに「移動」することになります。
別の方法として、アプリケーションにデータの表示と Phonograph へのデータの永続化を分けるパターンを定義します。これは、現在のビューを追跡するための状態変数を使用し、ユーザーがトリガーしたときに定期的にそのデータを Phonograph に保存することで実現できますが、すべての行を取得するクエリを自動的に再実行することはありません。このパターンでは、ユーザー体験が向上します(更新が即時に表示されます)が、設計がより複雑になります。
Table Storage Service
へのリクエストには、primaryKey 値のリストによる行の取得も含まれるため、すべての編集が含まれることが保証されています。そのため、次のようなイベントを連鎖させることが安全です。q_postEvent.success
-> q_getRowByPrimaryKey.run
この場合、主キー検索で取得される特定の行に書き込まれた変更は、結果に必ず含まれることが保証されます。
Table Storage Service
の Post Event
エンドポイントは、次の 3 つのイベントを処理します。rowAdded
、rowDeleted
、および rowModified
。
これらの 3 つのイベントのクエリは、primaryKey オブジェクトと payload オブジェクトを含む tableEditedEventPostRequest
を期待しています。以下のようになります。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{ "primaryKey": { "<primary_key_col>": "<primary_key_value>", "<second_primary_key_col>": "<second_value>" // 複数のカラムを手動編集インデックス作成時に指定した場合のみ }, "payload": { "type": "rowModified", // "rowAdded" または "rowDeleted" "rowModified": { // "rowAdded" または "rowDeleted" "columns": { "<col_a>": "<new_value>", "<col_b>": "<new_value2>" } } } }
rowDeleted
イベントには空の rowDeleted
オブジェクトがあります - 行を削除するために行を渡す必要はありません。
一般的なベストプラクティスとして、tableEditedEventPostRequest
を構築するための関数を使用します。これらは、望ましいワークフローと実装によって、多種多様な形をとることができます。
例えば、f_createTableEditEvent
という関数:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// 選択された行を定義します。getAllRowsの結果から選択された行のキーを使用して行を取得します。 var selectedRow={{q_getAllRows.result.rows.[w_rowsTable.selectedRowsKeys.[0]]}}; // 選択された行のカラムを更新します。 var updatedCols=selectedRow.columns; // 研究ノートを更新するための新たなテキストを取得します。 updatedCols.research_notes={{w_notesInput.text}} // 編集されたテーブルイベントのポストリクエストを作成します。 var tableEditedEventPostRequest = { "primaryKey":{ // 選択された行のプライマリキーの名前を取得します。 "name": selectedRow.primaryKey.name, }, "payload": { // ペイロードタイプとして"rowModified"を指定します。 "type": "rowModified", "rowModified": { // 更新されたカラムを指定します。 "columns": updatedCols, } } } // 編集されたテーブルイベントのポストリクエストを返します。 return tableEditedEventPostRequest;
上記のシンプルな関数の例では、q_getAllRows
のすべての行が w_rowsTable
ウィジェットに表示されます。行番号を表す行が選択キーとしてテーブルに追加され、w_rowsTable
の行を選択することで、q_getAllRows
の生の結果の中で行を見つけることができます。行が選択されると、w_notesInput
ウィジェットでユーザーが入力した値に research_notes
行の値を更新できます。これは、updatedCols.research_notes={{w_notesInput.text}}
という行で行われます。
関数 f_createTableEditEvent
の最後のステップは、updatedCols
オブジェクトを tableEditedEventPostRequest
変数に挿入し、関数の結果として返すことです。どれだけ複雑な処理が必要であっても、これが関数の出力であり、クエリに直接フィードすることができます。
関数が完了したら、関数の出力である tableEditedEventPostRequest
オブジェクトを、updateRow
クエリの適切なパラメーター欄に挿入できます(下の画像を参照)。
クエリに適切なパラメーターが設定されたので、テーブルの編集が必要な時だけクエリが実行されるように、クエリを実行する条件を定義します。
クエリエディターでクエリを表示している間に、Run の隣のドロップダウンメニューを使用して、Run manually をチェックします。これにより、ページのリロードや依存関係の変更時にクエリが実行されなくなります。
次に、ユーザーのアクションに応じてクエリが実行されるようにトリガーを設定します。これを行う最も簡単な方法は、button widget を追加し、button.clickevent
でクエリをトリガーすることですが、他にも多くの解決策があります。Slate アプリケーションにボタンウィジェットを追加し、クリック時にクエリを実行するように設定します。このクエリを実行しても、フォノグラフのキャッシュだけが更新されるため(Foundry の書き戻しデータセットでは編集がすぐには表示されません)。
また、フォームの入力を検証し、フィードバックテキストをフォームの横に表示するための関数を別途作成することが、ベストプラクティスとされています。これにより、ユーザーからの入力データに起因するデータ品質の問題が防止されます。このような機能を持つ関数は以下のようになります。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
var form { disableSubmit: false, // 提出を無効化: 初期状態ではfalse globalMessage: "", // グローバルメッセージ: 初期状態では空文字 fields : { i_widget1: { value: {{i_widget1.text}}, // i_widget1の値: 初期状態ではi_widget1.text message: "" // メッセージ: 初期状態では空文字 }, i_widget2: { value: {{i_widget2.text}}, // i_widget2の値: 初期状態ではi_widget2.text "message": "" // メッセージ: 初期状態では空文字 } // ...その他のフィールドも同様に設定... } // 値の検証、各ウィジェットのメッセージ生成、グローバルな有効状態判断のロジック // もし値が無効と判断された場合、disableSubmitをtrueに切り替える return form; // formを返す
その後、ウィジェットの disable
プロパティを "{{f_validateForm.disableSubmit}}" にリンクすることで、ボタンウィジェットを無効にすることができます。
新しい行の追加は行の編集と同じように動作します。上記の例で rowAdded
を rowModified
に置き換えるだけです。
ただし、既存の行と同じ主キーで新しい行を追加しようとすると失敗します。簡単なオプションとしては、行がすでに存在することをユーザーに警告するために、toast widget をトリガーすることです。
もう少しユーザーフレンドリーなオプションは、ユーザーが入力した主キーを使用して Get Rows
エンドポイントに対して q_validatePrimaryKey
クエリを行い、行がすでに存在するかどうかをチェックすることです。もし存在する場合は、f_createTableEditEvent
で rowModified
イベントを生成し、そうでない場合は rowAdded
を使用します。
行を削除するには、削除する行の主キーを含む rowDeleted
イベントを Post Event
エンドポイントに送信するだけです。
Copied!1 2 3 4 5 6 7 8 9 10 11 12
{ "primaryKey": { "<primary_key_col>": "<primary_key_value>" }, // 主キー: primary_key_colは主キーのカラム名、primary_key_valueは主キーの値 "payload": { "type": "rowDeleted", // タイプ: 行が削除されたことを示す "rowDeleted": {} // rowDeleted: 削除された行のデータ(現在は空) } }
Table Search Service
は、primaryKey による検索ではなく、値による行の検索が必要なときに search
エンドポイントを提供します。構文は ElasticSearch の検索構文に似ています。利用可能な検索タイプの完全な仕様は、API ドキュメンテーションでご覧いただけます。
すべての検索はネストされた hits
オブジェクトを返します。このオブジェクトを 行の取得 セクションの解析関数に渡し、rawData
変数への割り当てで .rows
を置き換えると、結果を表ウィジェットに表示可能な並列配列に分割するのと同じロジックを使用できます。
すべてのテキストタイプの行は、デフォルトの ElasticSearch インデクサーによって処理され、非単語文字で文字列をトークン化します。これにより、完全一致を探しているときに予期しない検索動作が発生する可能性があります。完全一致を行うには、queryString
検索タイプを使用し、検索項目を文字列リテラル文字でエスケープできます:\"8156-Apron 2 P.2\"
terms
フィルタータイプは、値の配列を取り、すべての行に対してマッチングを行うか、オプションで field
プロパティで指定された単一の行に対してマッチングを行います。用語がどのようにインデックス化されるかについては、上記の注釈を参照してください。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
{ "tableRids": [ "{{f_getTableId}}" // テーブルIDを取得する関数 ], "filter": { "type": "terms", // フィルターのタイプ "terms": { "field": "first_name", // フィルタリングするフィールド "terms": [ "agnese", // 名前:agnese "ailee", // 名前:ailee "woodman" // 名前:woodman ] } } }
queryString
フィルター処理のタイプは、自然言語検索と同等の検索を提供しようとします。 AND
や OR
のオペレーターを含めることができますし、正確な一致のために複数の単語を引用することも可能です:例えば、\"multi word exact match\"
Copied!1 2 3 4 5 6 7 8 9 10 11
{ "tableRids": [ "{{f_getTableId}}" // テーブルIDを取得する関数 ], "filter": { "type": "queryString", // クエリ文字列タイプのフィルタ "queryString": { "queryString": "jang" // 検索するクエリ文字列 } } }
範囲フィルターは、数値および日付タイプの行に対する比較フィルター処理を提供します。gt
、gte
、lt
、lte
に対応しています。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13
{ "tableRids": [ "{{f_getTableId}}" // テーブルIDを取得する ], "filter": { "type": "range", // 範囲フィルタのタイプ "range": { "field": "start_date", // 開始日フィールド "lt": "2018-01-01", // 2018年1月1日より前の日付 "format": "yyyy-MM-dd" // 日付の形式 } } }
パイプラインでgeohashesを生成している場合、これらのフィルターを使用して矩形範囲と半径検索をフィルター処理することができます。
これらのクエリの例については、Palantirチームにお問い合わせください。
すべてのフィルタータイプは、AND
およびOR
フィルタータイプとネストして、より複雑なフィルタリングロジックを構築することができます。一般的なパターンは、これらの複雑なクエリを関数を使用して生成し、関数の出力を単純にクエリのsearchRequest
パラメーターに含めることです。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
{ "tableRids": {{f_getTableId}}, // テーブルIDを取得する "filter": { "type": "and", // AND条件でフィルタリング "and": [ { "type": "queryString", // クエリ文字列によるフィルタリング "queryString": { "queryString": "pixoboo" // "pixoboo"というクエリ文字列を検索 } }, { "type": "terms", // 項目によるフィルタリング "terms": { "field": "first_name", // "first_name"というフィールドを対象に "terms": [ "harcourt" // "harcourt"という値が含まれているものを検索 ] } } ] } }
我々が書いたupdateRow
クエリは、Phonographに保存されているasteroid_notes
のコピーのみを更新します。データをFoundryに表示するためには、Foundry内のデータセットのプレビューページで"Build"をクリックする必要があります。
それが完了したら、我々の編集がasteroid_notes_edited
に表示されるのが見えます。
上記で見たPost Event
エンドポイントに加えて、Table Service
はPost Events for Table
エンドポイントを提供しています。このエンドポイントは、上記で生成したtableEditedEventPostRequest
の配列を期待しています。イベントは種類が混在することができます(rowModified
、rowAdded
、またはrowDeleted
)、ただし、特定のprimaryKeyは配列内で一度だけ現れることができ、例えば、同じprimaryKeyに対してrowModified
とrowDeleted
イベントを単一のリクエスト内に持つことはできません。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[ // イベントリクエスト1 { "primaryKey": { "primary_key_col": "primary_key_value", }, "payload": { "type": "rowModified", // "rowAdded" または "rowDeleted" "rowModified": { // "rowAdded" または "rowDeleted" "columns": { "col_a": "value", } } } }, { "primaryKey": { "primary_key_col": "different_primary_key_value", }, "payload": { "type": "rowDeleted", // "rowAdded" または "rowDeleted" "rowDeleted": {} } }, 等...
以下では、一括エンドポイントとEventsフレームワークをどのように使用して、変更を行う際のレイテンシを処理するためのより強力なソリューションを構築することができるかについて説明します。
手動編集キャッシュの基礎となるアーキテクチャのため、編集が Post Event
の成功した呼び出し直後にプライマリインデックスにあることは保証されていません。現在、Get All Rows
と Get Rows
の呼び出しが同期的になるように作業が進行中であり、q_getAllRows
を q_postEditEvent
クエリの成功にトリガーするように設定すれば、編集が確実に表示されます。しかし、search
エンドポイントに依存している場合、検索インデックスが更新されるまでの数秒のレイテンシを考慮に入れる必要があります。
最も簡単な方法は、編集クエリと全行取得クエリの間に toast を挿入することです。q_postEditEvent.success
イベントでトーストをトリガーし、3-4s (3000-4000ms)の時間を与えます。その後、w_editSuccessToast.closed
イベントで q_getAllRows
クエリをトリガーすると、インデックスが更新されるのに十分な時間が提供されます。
より複雑なワークフローの場合、Slateアプリの表示に使用される状態と編集インデックスの状態を分離するための追加の作業を検討することがあります。これを行うには、ページの読み込み時に q_getAllRows
クエリの結果でSlate変数を埋め込み、それが "フロントエンド状態" になります。すべての編集/削除/更新イベントは、バックエンドへのクエリを直接トリガーするのではなく、このフロントエンド状態変数に変更を加えます。定期的にフロントエンド変数の状態とクエリからのデータとの差分を取り、すべての変更を適用するための一括クエリのペイロードを作成することができます。
また、トーストや "未保存の変更" カウンターなどの形でユーザーフィードバックを提供したいと思うかもしれませんし、すべての変更を保存するための手動ボタンをクリックすることも考慮に入れるでしょう。この設定は、複雑で長期的なアプリケーション以外のものには重すぎます。ほとんどの場合、トーストのアプローチが十分であり、Get Rows
と Get All Rows
エンドポイントへの改善により、ほぼすべてのケースでこれを不要にするはずですので、このオプションを検討している場合は、さらなる議論のためにPalantirチームに連絡するのが最善です。
search
エンドポイントは、インデックス化されたデータ全体で統計を生成したり、値をバケット化したりするための集計もサポートしています。
ElasticSearch 2.0 Aggregationの構文の一部がサポートされています:value_count
、max
、geohash_grid
、terms
、top_hits
、sum
、cardinality
、avg
、nested
、filter
、histogram
、min
。
Elasticsearchの制限により、一部の集計の結果は近似値となる可能性があることに注意してください。集計のタイプを使用する前に、Elasticsearchのドキュメンテーションを参照し、それが正確なものか近似値かを理解してください。近似値である場合、それがユーザーのユースケースにとって許容可能かどうかを決定してから続行してください。
以下は構文の簡単な例です。文字列フィールドで集計しているため、visits
フィールドの生バージョンを使用する必要があります。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
{ // テーブルIDの取得 "tableRids": [ "{{f_getTableId}}" ], // フィルタリング条件 "filter": { "type": "matchAll", "matchAll": {} }, // 集計条件 "aggregations": { "visits": { "terms": { "field": "visits.raw" } } } }
上記のクエリは、クエリの filter
セクションからすべての行を visits
フィールドの値でバケットに入れ、カウントを返します。集約値のみに興味がある場合は、 pageSize
を 0
に設定して個々のレコードヒットを結果から削除し、アプリケーションのロード時間とメモリプレッシャーを軽減します。
返り値の形式は以下のようになります:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
"aggregations": { "genders": { "doc_count_error_upper_bound": 0, // ドキュメント数の誤差の上限 "sum_other_doc_count": 30, // その他のドキュメント数の合計 "buckets": [ { "key": "daily", // キー: "毎日" "doc_count": 148 // ドキュメント数 }, { "key": "often", // キー: "しばしば" "doc_count": 141 // ドキュメント数 }, { "key": "weekly", // キー: "毎週" "doc_count": 129 // ドキュメント数 }, ... ] } }
各集約タイプは、わずかに異なる戻り構文を持ちますが、行から列へ 関数は、チャートやテーブルのような Slate ウィジェットでこのタイプのデータを操作する際に有用であることがわかるでしょう。