インデックスソート
Elasticsearchで新しいインデックスを作成する際、各シャード内のセグメントがどのようにソートされるかを設定することができます。デフォルトでは、Luceneはソートを適用しません。index.sort.*
設定は、各セグメント内のドキュメントをソートするために使用されるフィールドを定義します。
ネストされたオブジェクトを持つマッピングにインデックスソートを適用することは許可されていますが、index.sort.*
設定にネストされたフィールドが含まれていない必要があります。
例えば、以下の例は単一のフィールドでソートを定義する方法を示しています:
Python
resp = client.indices.create(
index="my-index-000001",
settings={
"index": {
"sort.field": "date",
"sort.order": "desc"
}
},
mappings={
"properties": {
"date": {
"type": "date"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
settings: {
index: {
'sort.field' => 'date',
'sort.order' => 'desc'
}
},
mappings: {
properties: {
date: {
type: 'date'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
settings: {
index: {
"sort.field": "date",
"sort.order": "desc",
},
},
mappings: {
properties: {
date: {
type: "date",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000001
{
"settings": {
"index": {
"sort.field": "date",
"sort.order": "desc"
}
},
"mappings": {
"properties": {
"date": {
"type": "date"
}
}
}
}
このインデックスはdate フィールドでソートされています |
|
… 降順で。 |
インデックスを複数のフィールドでソートすることも可能です:
Python
resp = client.indices.create(
index="my-index-000001",
settings={
"index": {
"sort.field": [
"username",
"date"
],
"sort.order": [
"asc",
"desc"
]
}
},
mappings={
"properties": {
"username": {
"type": "keyword",
"doc_values": True
},
"date": {
"type": "date"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
settings: {
index: {
'sort.field' => [
'username',
'date'
],
'sort.order' => [
'asc',
'desc'
]
}
},
mappings: {
properties: {
username: {
type: 'keyword',
doc_values: true
},
date: {
type: 'date'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
settings: {
index: {
"sort.field": ["username", "date"],
"sort.order": ["asc", "desc"],
},
},
mappings: {
properties: {
username: {
type: "keyword",
doc_values: true,
},
date: {
type: "date",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000001
{
"settings": {
"index": {
"sort.field": [ "username", "date" ],
"sort.order": [ "asc", "desc" ]
}
},
"mappings": {
"properties": {
"username": {
"type": "keyword",
"doc_values": true
},
"date": {
"type": "date"
}
}
}
}
このインデックスは最初にusername でソートされ、その後date でソートされます |
|
… username フィールドは昇順で、date フィールドは降順で。 |
インデックスソートは以下の設定をサポートします:
index.sort.field
- インデックスをソートするために使用されるフィールドのリスト。ここでは
boolean
、numeric
、date
、およびkeyword
フィールドがdoc_values
を持つことが許可されています。 index.sort.order
- 各フィールドに使用するソート順。順序オプションは以下の値を持つことができます:
asc
:昇順desc
:降順。
index.sort.mode
- Elasticsearchは多値フィールドによるソートをサポートしています。モードオプションは、ドキュメントをソートするために選択される値を制御します。モードオプションは以下の値を持つことができます:
min
:最小値を選択。max
:最大値を選択。
index.sort.missing
- missingパラメータは、フィールドが欠落しているドキュメントがどのように扱われるかを指定します。missing値は以下の値を持つことができます:
_last
:フィールドに値がないドキュメントは最後にソートされます。_first
:フィールドに値がないドキュメントは最初にソートされます。
インデックスソートはインデックス作成時にのみ一度定義できます。既存のインデックスにソートを追加または更新することは許可されていません。インデックスソートは、ドキュメントがフラッシュおよびマージ時にソートされる必要があるため、インデックススループットにコストがかかります。この機能を有効にする前に、アプリケーションへの影響をテストする必要があります。
検索リクエストの早期終了
デフォルトでは、Elasticsearchの検索リクエストは、指定されたソートでソートされた上位のドキュメントを取得するために、クエリに一致するすべてのドキュメントを訪問する必要があります。しかし、インデックスソートと検索ソートが同じである場合、N個の上位ランクのドキュメントをグローバルに取得するために、各セグメントで訪問する必要があるドキュメントの数を制限することが可能です。例えば、タイムスタンプフィールドでソートされたイベントを含むインデックスがあるとしましょう:
Python
resp = client.indices.create(
index="events",
settings={
"index": {
"sort.field": "timestamp",
"sort.order": "desc"
}
},
mappings={
"properties": {
"timestamp": {
"type": "date"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'events',
body: {
settings: {
index: {
'sort.field' => 'timestamp',
'sort.order' => 'desc'
}
},
mappings: {
properties: {
timestamp: {
type: 'date'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "events",
settings: {
index: {
"sort.field": "timestamp",
"sort.order": "desc",
},
},
mappings: {
properties: {
timestamp: {
type: "date",
},
},
},
});
console.log(response);
コンソール
PUT events
{
"settings": {
"index": {
"sort.field": "timestamp",
"sort.order": "desc"
}
},
"mappings": {
"properties": {
"timestamp": {
"type": "date"
}
}
}
}
このインデックスはタイムスタンプで降順にソートされています(最新が最初) |
最後の10件のイベントを検索するには:
Python
resp = client.search(
index="events",
size=10,
sort=[
{
"timestamp": "desc"
}
],
)
print(resp)
Ruby
response = client.search(
index: 'events',
body: {
size: 10,
sort: [
{
timestamp: 'desc'
}
]
}
)
puts response
Js
const response = await client.search({
index: "events",
size: 10,
sort: [
{
timestamp: "desc",
},
],
});
console.log(response);
コンソール
GET /events/_search
{
"size": 10,
"sort": [
{ "timestamp": "desc" }
]
}
Elasticsearchは、各セグメントの上位ドキュメントがすでにインデックスでソートされていることを検出し、各セグメントごとに最初のNドキュメントのみを比較します。クエリに一致する他のドキュメントは、結果の総数をカウントし、集計を構築するために収集されます。
最後の10件のイベントのみを探していて、クエリに一致するドキュメントの総数には興味がない場合は、track_total_hits
をfalseに設定できます:
Python
resp = client.search(
index="events",
size=10,
sort=[
{
"timestamp": "desc"
}
],
track_total_hits=False,
)
print(resp)
Ruby
response = client.search(
index: 'events',
body: {
size: 10,
sort: [
{
timestamp: 'desc'
}
],
track_total_hits: false
}
)
puts response
Js
const response = await client.search({
index: "events",
size: 10,
sort: [
{
timestamp: "desc",
},
],
track_total_hits: false,
});
console.log(response);
コンソール
GET /events/_search
{
"size": 10,
"sort": [
{ "timestamp": "desc" }
],
"track_total_hits": false
}
インデックスソートが上位ドキュメントをランク付けするために使用され、各セグメントは最初の10件の一致後にコレクションを早期終了します。 |
この場合、Elasticsearchはドキュメントの数をカウントしようとせず、各セグメントでN件のドキュメントが収集されるとすぐにクエリを終了できるようになります。
コンソール-結果
{
"_shards": ...
"hits" : {
"max_score" : null,
"hits" : []
},
"took": 20,
"timed_out": false
}
クエリに一致するヒットの総数は早期終了のため不明です。 |
集計は、track_total_hits
の値に関係なく、クエリに一致するすべてのドキュメントを収集します。