検索API
検索は、1つ以上のクエリで構成され、これらが組み合わされてElasticsearchに送信されます。検索のクエリに一致するドキュメントは、レスポンスのヒットまたは検索結果として返されます。
検索には、クエリをより良く処理するために使用される追加情報が含まれる場合もあります。たとえば、検索は特定のインデックスに制限されるか、特定の数の結果のみを返すことができます。
検索APIを使用して、Elasticsearchのデータストリームまたはインデックスに保存されたデータを検索および集約できます。APIのquery
リクエストボディパラメータは、Query DSLで記述されたクエリを受け入れます。
検索を実行する
次のリクエストは、match
クエリを使用してmy-index-000001
を検索します。このクエリは、user.id
の値がkimchy
のドキュメントに一致します。
Python
resp = client.search(
index="my-index-000001",
query={
"match": {
"user.id": "kimchy"
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
query: {
match: {
'user.id' => 'kimchy'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
query: {
match: {
"user.id": "kimchy",
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"query": {
"match": {
"user.id": "kimchy"
}
}
}
APIのレスポンスは、hits.hits
プロパティ内のクエリに一致する上位10件のドキュメントを返します。
コンソール-結果
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "my-index-000001",
"_id": "kxWFcnMByiguvud1Z8vC",
"_score": 1.3862942,
"_source": {
"@timestamp": "2099-11-15T14:12:12",
"http": {
"request": {
"method": "get"
},
"response": {
"bytes": 1070000,
"status_code": 200
},
"version": "1.1"
},
"message": "GET /search HTTP/1.1 200 1070000",
"source": {
"ip": "127.0.0.1"
},
"user": {
"id": "kimchy"
}
}
}
]
}
}
一般的な検索オプション
次のオプションを使用して、検索をカスタマイズできます。
Query DSL
Query DSLは、結果を得るために組み合わせて使用できるさまざまなクエリタイプをサポートしています。クエリタイプには次のものが含まれます:
- ブールおよびその他の複合クエリ、これにより、複数の基準に基づいてクエリを組み合わせて結果を一致させることができます
- 正確な一致をフィルタリングおよび見つけるためのタームレベルクエリ
- 検索エンジンで一般的に使用される全文検索クエリ
- 地理および空間クエリ
集約
検索集約を使用して、検索結果の統計やその他の分析を取得できます。集約は、次のような質問に答えるのに役立ちます:
- サーバーの平均応答時間は?
- ネットワーク上のユーザーによってヒットされた上位のIPアドレスは?
- 顧客ごとの総取引収益は?
複数のデータストリームおよびインデックスを検索
カンマ区切りの値とgrepのようなインデックスパターンを使用して、同じリクエストで複数のデータストリームおよびインデックスを検索できます。特定のインデックスからの検索結果をブーストすることもできます。複数のデータストリームおよびインデックスを検索を参照してください。
検索結果をページネート
デフォルトでは、検索は一致する上位10件のヒットのみを返します。より多くまたは少ないドキュメントを取得するには、検索結果をページネートを参照してください。
選択したフィールドを取得
検索レスポンスのhits.hits
プロパティには、各ヒットの完全なドキュメント_source
が含まれています。_source
や他のフィールドのサブセットのみを取得するには、選択したフィールドを取得を参照してください。
検索結果をソート
デフォルトでは、検索ヒットは_score
によってソートされます。これは、各ドキュメントがクエリにどれだけ一致するかを測定する関連スコアです。これらのスコアの計算をカスタマイズするには、script_score
クエリを使用します。他のフィールド値で検索ヒットをソートするには、検索結果をソートを参照してください。
非同期検索を実行
Elasticsearchの検索は、大量のデータを迅速に処理するように設計されており、しばしばミリ秒単位で結果を返します。このため、検索はデフォルトで同期です。検索リクエストは、完全な結果を待ってからレスポンスを返します。
ただし、大規模なデータセットや複数のクラスターにわたる検索では、完全な結果が得られるまでに時間がかかる場合があります。
長時間の待機を避けるために、非同期またはasync検索を実行できます。非同期検索を使用すると、長時間実行される検索の部分的な結果を今すぐ取得し、後で完全な結果を取得できます。
クエリにのみ存在するフィールドを定義する
データをインデックス化してから検索するのではなく、検索クエリの一部としてのみ存在するランタイムフィールドを定義できます。検索リクエストでruntime_mappings
セクションを指定してランタイムフィールドを定義し、オプションでPainlessスクリプトを含めることができます。
たとえば、次のクエリはday_of_week
というランタイムフィールドを定義します。含まれているスクリプトは、@timestamp
フィールドの値に基づいて曜日を計算し、emit
を使用して計算された値を返します。
クエリには、day_of_week
に対して動作するterms aggregationも含まれています。
Python
resp = client.search(
index="my-index-000001",
runtime_mappings={
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum\n .getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
aggs={
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "my-index-000001",
runtime_mappings: {
day_of_week: {
type: "keyword",
script: {
source:
"emit(doc['@timestamp'].value.dayOfWeekEnum\n .getDisplayName(TextStyle.FULL, Locale.ENGLISH))",
},
},
},
aggs: {
day_of_week: {
terms: {
field: "day_of_week",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": {
"source":
"""emit(doc['@timestamp'].value.dayOfWeekEnum
.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"""
}
}
},
"aggs": {
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
}
}
レスポンスには、day_of_week
ランタイムフィールドに基づく集約が含まれています。buckets
の下には、key
の値がSunday
のkey
があります。このクエリは、day_of_week
ランタイムフィールドに定義されたスクリプトに基づいてこの値を動的に計算しましたが、フィールドをインデックス化することはありませんでした。
コンソール-結果
{
...
***
"aggregations" : {
"day_of_week" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Sunday",
"doc_count" : 5
}
]
}
}
}
検索タイムアウト
デフォルトでは、検索リクエストはタイムアウトしません。リクエストは、各シャードから完全な結果を待ってからレスポンスを返します。
非同期検索は長時間実行される検索用に設計されていますが、timeout
パラメータを使用して、各シャードが完了するまで待機する期間を指定することもできます。各シャードは、指定された時間内にヒットを収集します。期間が終了したときに収集が完了していない場合、Elasticsearchはその時点までに蓄積されたヒットのみを使用します。検索リクエストの全体的なレイテンシは、検索に必要なシャードの数と同時シャードリクエストの数に依存します。
Python
resp = client.search(
index="my-index-000001",
timeout="2s",
query={
"match": {
"user.id": "kimchy"
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
timeout: '2s',
query: {
match: {
'user.id' => 'kimchy'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
timeout: "2s",
query: {
match: {
"user.id": "kimchy",
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"timeout": "2s",
"query": {
"match": {
"user.id": "kimchy"
}
}
}
すべての検索リクエストに対してクラスター全体のデフォルトタイムアウトを設定するには、クラスタ設定APIを使用してsearch.default_search_timeout
を構成します。このグローバルタイムアウト期間は、リクエストにtimeout
引数が渡されない場合に使用されます。グローバル検索タイムアウトが検索リクエストが完了する前に期限切れになると、リクエストはタスクキャンセルを使用してキャンセルされます。search.default_search_timeout
設定のデフォルトは-1
(タイムアウトなし)です。
検索キャンセル
タスク管理APIを使用して検索リクエストをキャンセルできます。Elasticsearchは、クライアントのHTTP接続が閉じると自動的に検索リクエストをキャンセルします。検索リクエストが中止またはタイムアウトした場合、HTTP接続を閉じるようにクライアントを設定することをお勧めします。
総ヒット数を追跡
一般的に、すべての一致を訪問せずに総ヒット数を正確に計算することはできません。これは、多くのドキュメントに一致するクエリにとってコストがかかります。track_total_hits
パラメータを使用すると、総ヒット数をどのように追跡するかを制御できます。ヒット数の下限があることがしばしば十分であるため、デフォルトは10,000
に設定されています。これは、リクエストが10,000
ヒットまで正確に総ヒット数をカウントすることを意味します。特定の閾値を超えた後に正確なヒット数が必要ない場合、検索を高速化するための良いトレードオフです。
#### Python
``````python
resp = client.search(
index="my-index-000001",
track_total_hits=True,
query={
"match": {
"user.id": "elkbee"
}
},
)
print(resp)
`
Ruby
response = client.search(
index: 'my-index-000001',
body: {
track_total_hits: true,
query: {
match: {
'user.id' => 'elkbee'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
track_total_hits: true,
query: {
match: {
"user.id": "elkbee",
},
},
});
console.log(response);
コンソール
GET my-index-000001/_search
{
"track_total_hits": true,
"query": {
"match" : {
"user.id" : "elkbee"
}
}
}
コンソール-結果
{
"_shards": ...
"timed_out": false,
"took": 100,
"hits": {
"max_score": 1.0,
"total" : {
"value": 2048,
"relation": "eq"
},
"hits": ...
}
}
クエリに一致するヒットの総数。 | |
カウントは正確です(例:"eq" は等しいを意味します)。 |
#### Python
``````python
resp = client.search(
index="my-index-000001",
track_total_hits=100,
query={
"match": {
"user.id": "elkbee"
}
},
)
print(resp)
`
Ruby
response = client.search(
index: 'my-index-000001',
body: {
track_total_hits: 100,
query: {
match: {
'user.id' => 'elkbee'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
track_total_hits: 100,
query: {
match: {
"user.id": "elkbee",
},
},
});
console.log(response);
コンソール
GET my-index-000001/_search
{
"track_total_hits": 100,
"query": {
"match": {
"user.id": "elkbee"
}
}
}
レスポンス内のhits.total.relation
は、hits.total.value
で返される値が正確であるか("eq"
)または総数の下限であるか("gte"
)を示します。
コンソール-結果
{
"_shards": ...
"timed_out": false,
"took": 30,
"hits": {
"max_score": 1.0,
"total": {
"value": 42,
"relation": "eq"
},
"hits": ...
}
}
42ドキュメントがクエリに一致します | |
カウントは正確です("eq" ) |
… これは、total
で返されるヒット数が正確であることを示しています。
クエリに一致するヒットの総数がtrack_total_hits
に設定された値を超える場合、レスポンス内の総ヒット数は、返された値が下限であることを示します:
コンソール-結果
{
"_shards": ...
"hits": {
"max_score": 1.0,
"total": {
"value": 100,
"relation": "gte"
},
"hits": ...
}
}
クエリに一致するドキュメントが少なくとも100件あります | |
これは下限です("gte" )。 |
総ヒット数を全く追跡する必要がない場合は、このオプションをfalse
に設定することでクエリ時間を改善できます:
Python
resp = client.search(
index="my-index-000001",
track_total_hits=False,
query={
"match": {
"user.id": "elkbee"
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
track_total_hits: false,
query: {
match: {
'user.id' => 'elkbee'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
track_total_hits: false,
query: {
match: {
"user.id": "elkbee",
},
},
});
console.log(response);
コンソール
GET my-index-000001/_search
{
"track_total_hits": false,
"query": {
"match": {
"user.id": "elkbee"
}
}
}
コンソール-結果
{
"_shards": ...
"timed_out": false,
"took": 10,
"hits": {
"max_score": 1.0,
"hits": ...
}
}
ヒットの総数は不明です。 |
最後に、リクエストで"track_total_hits"
をtrue
に設定することで、正確なカウントを強制できます。
track_total_hits
パラメータは、ヒットカウントの正確さとパフォーマンスをトレードオフすることを可能にします。一般的に、track_total_hits
の値が低いほど、クエリは速くなり、false
が最も速い結果を返します。track_total_hits
をtrueに設定すると、Elasticsearchは正確なヒットカウントを返しますが、Max WAND最適化を無効にするため、クエリパフォーマンスが低下する可能性があります。
一致するドキュメントを迅速に確認
特定のクエリに一致するドキュメントがあるかどうかを知りたいだけの場合は、size
を0
に設定して、検索結果に興味がないことを示すことができます。また、terminate_after
を1
に設定して、最初の一致するドキュメントが見つかったときにクエリの実行を終了できることを示すこともできます(シャードごと)。
Python
resp = client.search(
q="user.id:elkbee",
size="0",
terminate_after="1",
)
print(resp)
Ruby
response = client.search(
q: 'user.id:elkbee',
size: 0,
terminate_after: 1
)
puts response
Js
const response = await client.search({
q: "user.id:elkbee",
size: 0,
terminate_after: 1,
});
console.log(response);
コンソール
GET /_search?q=user.id:elkbee&size=0&terminate_after=1
レスポンスには、`````0`````に設定されていたため、ヒットは含まれません。`````hits.total`````は、`````0`````と等しいか、クエリが早期に終了したときに一致するドキュメントが少なくとも存在したことを示す`````0`````より大きくなります。また、クエリが早期に終了した場合、レスポンス内の`````terminated_early`````フラグは`````true`````に設定されます。一部のクエリは、インデックス統計からヒット数を直接取得できるため、クエリを実行する必要がなく、はるかに速くなります。そのような状況では、ドキュメントは収集されず、返された`````total.hits`````は`````terminate_after`````より大きく、`````terminated_early`````は`````false`````に設定されます。
[](#31fa804420aad7728f9ba9f20dc1a9c5)
#### コンソール-結果
``````console-result
{
"took": 3,
"timed_out": false,
"terminated_early": true,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": null,
"hits": []
}
}
`
レスポンス内のtook
時間は、このリクエストが処理にかかったミリ秒を含み、ノードがクエリを受信した後すぐに始まり、すべての検索関連作業が完了するまで続き、上記のJSONがクライアントに返される前の時間を含みます。これは、スレッドプールで待機している時間、クラスター全体での分散検索の実行、およびすべての結果を収集する時間を含みます。