- ハイライト
- 統一ハイライター
- プレーンハイライター
- ファストベクターハイライター
- オフセット戦略
- ハイライト設定
- ハイライトの例
- グローバル設定をオーバーライド
- Python
- Ruby
- Js
- コンソール
- ハイライトクエリを指定
- Python
- Ruby
- Js
- コンソール
- ハイライタータイプを設定
- Python
- Ruby
- Js
- コンソール
- ハイライトタグを構成
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- すべてのフィールドでハイライト
- Python
- Ruby
- Js
- コンソール
- 複数フィールドの一致を組み合わせる
- Python
- Js
- コンソール
- Python
- Js
- コンソール
- Python
- Js
- コンソール
- コンソール-結果
- Python
- Js
- コンソール
- コンソール-結果
- Python
- Js
- コンソール
- Python
- Js
- コンソール
- Python
- Js
- コンソール
- コンソール-結果
- Python
- Js
- コンソール
- コンソール-結果
- Python
- Js
- コンソール
- コンソール-結果
- Js
- Js
- ハイライトされたフィールドの明示的な順序
- Python
- Ruby
- Js
- コンソール
- ハイライトされたフラグメントを制御
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- 投稿リストを使用してハイライト
- Python
- Ruby
- Js
- コンソール
- Python
- Ruby
- Js
- コンソール
- プレーンハイライターのためのフラグメンターを指定
- Python
- Ruby
- Js
- Console
- Console-Result
- Python
- Ruby
- Js
- Console
- Console-Result
- Js
- Js
- グローバル設定をオーバーライド
ハイライト
ハイライターを使用すると、検索結果の1つまたは複数のフィールドからハイライトされたスニペットを取得でき、ユーザーにクエリの一致がどこにあるかを示すことができます。ハイライトをリクエストすると、レスポンスには、ハイライトされたフィールドとハイライトされたフラグメントを含む追加の highlight
要素が各検索ヒットに含まれます。
ハイライターは、ハイライトする用語を抽出する際にクエリのブール論理を反映しません。したがって、複雑なブールクエリ(例:ネストされたブールクエリ、minimum_should_match
を使用するクエリなど)では、クエリの一致に対応しない文書の一部がハイライトされる場合があります。
ハイライトにはフィールドの実際のコンテンツが必要です。フィールドが保存されていない場合(マッピングが store
を true
に設定していない場合)、実際の _source
がロードされ、関連するフィールドが _source
から抽出されます。
たとえば、デフォルトのハイライターを使用して各検索ヒットの content
フィールドのハイライトを取得するには、highlight
オブジェクトをリクエストボディに含めて content
フィールドを指定します。
Python
resp = client.search(
query={
"match": {
"content": "kimchy"
}
},
highlight={
"fields": {
"content": {}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
content: 'kimchy'
}
},
highlight: {
fields: {
content: {}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
content: "kimchy",
},
},
highlight: {
fields: {
content: {},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query": {
"match": { "content": "kimchy" }
},
"highlight": {
"fields": {
"content": {}
}
}
}
Elasticsearch は、unified
、plain
、fvh
(ファストベクターハイライター)の 3 つのハイライターをサポートしています。各フィールドに使用するハイライター type
を指定できます。
統一ハイライター
unified
ハイライターは、Lucene 統一ハイライターを使用します。このハイライターは、テキストを文に分割し、BM25 アルゴリズムを使用して、個々の文をコーパス内の文書のようにスコア付けします。また、正確なフレーズおよびマルチターム(ファジー、プレフィックス、正規表現)ハイライトもサポートしています。unified
ハイライターは、複数のフィールドからの一致を 1 つの結果に結合できます(matched_fields
を参照)。これがデフォルトのハイライターです。
プレーンハイライター
plain
ハイライターは、標準の Lucene ハイライターを使用します。これは、フレーズクエリにおける単語の重要性や単語の位置基準を理解することに関して、クエリの一致ロジックを反映しようとします。
plain
ハイライターは、単一フィールド内の単純なクエリ一致をハイライトするのに最適です。クエリロジックを正確に反映するために、メモリ内に小さなインデックスを作成し、Lucene のクエリ実行プランナーを介して元のクエリ基準を再実行して、現在の文書の低レベルの一致情報にアクセスします。これは、ハイライトする必要があるすべてのフィールドとすべての文書に対して繰り返されます。複雑なクエリで多くの文書の多くのフィールドをハイライトしたい場合は、unified
ハイライターを postings
または term_vector
フィールドで使用することをお勧めします。
ファストベクターハイライター
fvh
ハイライターは、Lucene ファストベクターハイライターを使用します。このハイライターは、マッピングで term_vector
が with_positions_offsets
に設定されているフィールドで使用できます。ファストベクターハイライターは、
boundary_scanner
でカスタマイズできます。- インデックスのサイズを増やす
term_vector
をwith_positions_offsets
に設定する必要があります。 - 複数のフィールドからの一致を 1 つの結果に結合できます。
matched_fields
を参照してください。 - 異なる位置での一致に異なる重みを割り当てることができ、フレーズ一致が用語一致の上にソートされるようにすることができます。これは、フレーズ一致を用語一致よりも強調するブースティングクエリをハイライトする際に便利です。
fvh
ハイライターは、スパンクエリをサポートしていません。スパンクエリのサポートが必要な場合は、unified
ハイライターなどの代替ハイライターを試してください。
オフセット戦略
クエリされている用語から意味のある検索スニペットを作成するには、ハイライターは元のテキスト内の各単語の開始および終了文字オフセットを知る必要があります。これらのオフセットは、次の方法で取得できます。
- 投稿リスト。マッピングで
index_options
がoffsets
に設定されている場合、unified
ハイライターはこの情報を使用して、テキストを再分析することなく文書をハイライトします。元のクエリを投稿に直接再実行し、一致するオフセットをインデックスから抽出し、収集をハイライトされた文書に制限します。これは、大きなフィールドを持つ場合に重要です。なぜなら、ハイライトするテキストを再分析する必要がないからです。また、term_vectors
を使用するよりもディスクスペースが少なくて済みます。 - 用語ベクター。マッピングで
term_vector
情報がterm_vector
をwith_positions_offsets
に設定することによって提供される場合、unified
ハイライターは自動的にterm_vector
を使用してフィールドをハイライトします。これは特に大きなフィールド(>1MB
)や、prefix
やwildcard
のようなマルチタームクエリをハイライトする際に高速です。なぜなら、各文書の用語の辞書にアクセスできるからです。fvh
ハイライターは常に用語ベクターを使用します。 - プレーンハイライト。これは、他の選択肢がない場合に
unified
によって使用されます。これは、メモリ内に小さなインデックスを作成し、Lucene のクエリ実行プランナーを介して元のクエリ基準を再実行して、現在の文書の低レベルの一致情報にアクセスします。これは、ハイライトする必要があるすべてのフィールドとすべての文書に対して繰り返されます。plain
ハイライターは常にプレーンハイライトを使用します。
大きなテキストのプレーンハイライトには、かなりの時間とメモリが必要になる場合があります。これに対して保護するために、分析される最大文字数は 1000000 に制限されています。このデフォルトの制限は、特定のインデックスに対して index.highlight.max_analyzed_offset
設定で変更できます。
ハイライト設定
ハイライト設定は、グローバルレベルで設定でき、フィールドレベルでオーバーライドできます。
- boundary_chars
- 各境界文字を含む文字列。デフォルトは
.,!? \t\n
です。 - boundary_max_scan
境界文字をスキャンする距離。デフォルトは
20
です。- boundary_scanner
- ハイライトされたフラグメントを分割する方法を指定します:
chars
、sentence
、またはword
。unified
およびfvh
ハイライターに対してのみ有効です。unified
ハイライターのデフォルトはsentence
です。fvh
ハイライターのデフォルトはchars
です。chars
boundary_chars
で指定された文字をハイライトの境界として使用します。boundary_max_scan
設定は、境界文字をスキャンする距離を制御します。fvh
ハイライターに対してのみ有効です。sentence
- Java の BreakIterator によって決定された次の文の境界でハイライトされたフラグメントを分割します。
boundary_scanner_locale
で使用するロケールを指定できます。unified
ハイライターと一緒に使用されると、sentence
スキャナーは、fragment_size
よりも大きい文をfragment_size
の隣の最初の単語の境界で分割します。fragment_size
を 0 に設定すると、文を分割しなくなります。 word
- Java の BreakIterator によって決定された次の単語の境界でハイライトされたフラグメントを分割します。
boundary_scanner_locale
で使用するロケールを指定できます。
- boundary_scanner_locale
- 文と単語の境界を検索するために使用されるロケールを制御します。このパラメータは、
"en-US"
、"fr-FR"
、"ja-JP"
のような言語タグの形式を取ります。詳細は、ロケール言語タグ ドキュメントを参照してください。デフォルト値は Locale.ROOT です。 - encoder
- スニペットを HTML エンコードする必要があるかどうかを示します:
default
(エンコードなし)またはhtml
(スニペットテキストを HTML エスケープし、ハイライトタグを挿入します) - fields
- ハイライトを取得するフィールドを指定します。ワイルドカードを使用してフィールドを指定できます。たとえば、
comment_*
を指定して、comment_
で始まるすべての text、match_only_text、および keyword フィールドのハイライトを取得できます。
テキスト、match_only_text、およびキーワードフィールドのみが、ワイルドカードを使用する場合にハイライトされます。カスタムマッパーを使用していても、フィールドでハイライトする必要がある場合は、そのフィールド名を明示的に指定する必要があります。 - fragmenter
- ハイライトスニペット内のテキストを分割する方法を指定します:
simple
またはspan
。plain
ハイライターに対してのみ有効です。デフォルトはspan
です。 - force_source
- 非推奨。このパラメータは効果がありません。
simple
- テキストを同じサイズのフラグメントに分割します。
span
- テキストを同じサイズのフラグメントに分割しますが、ハイライトされた用語の間でテキストを分割しないようにします。これは、フレーズをクエリする際に役立ちます。デフォルト。
- fragment_offset
- ハイライトを開始したいマージンを制御します。
fvh
ハイライターを使用する場合にのみ有効です。 - fragment_size
- 文字数でのハイライトフラグメントのサイズ。デフォルトは 100 です。
- highlight_query
- 検索クエリ以外のクエリの一致をハイライトします。これは、リスコアクエリを使用する場合に特に便利です。なぜなら、デフォルトではハイライトによって考慮されないからです。
Elasticsearch は、highlight_query
が検索クエリを含むかどうかを検証しないため、正当なクエリ結果がハイライトされないように定義することが可能です。一般的には、highlight_query
の一部として検索クエリを含めるべきです。 - matched_fields
- 複数のフィールドの一致を組み合わせて、単一のフィールドをハイライトします。これは、同じ文字列を異なる方法で分析するマルチフィールドに最も直感的です。
unified
および fvh ハイライターに対して有効ですが、このオプションの動作は各ハイライターで異なります。
unified
ハイライターの場合:
matched_fields
配列には、ハイライトしたい元のフィールドを含めないでください。元のフィールドは自動的にmatched_fields
に追加され、ハイライト時にその一致を除外する方法はありません。matched_fields
および元のフィールドは、異なる戦略(offsets
の有無、term_vectors
の有無)でインデックス化できます。- 一致が組み合わされる元のフィールドのみがロードされるため、そのフィールドのみが
store
をyes
に設定することで利益を得ます。
fvh
ハイライターの場合:
matched_fields
配列には、必要に応じて元のフィールドが含まれる場合と含まれない場合があります。元のフィールドの一致をハイライトに含めたい場合は、それをmatched_fields
配列に追加します。- すべての
matched_fields
はterm_vector
をwith_positions_offsets
に設定する必要があります。 一致が組み合わされる元のフィールドのみがロードされるため、そのフィールドのみが
store
をyes
に設定することで利益を得ます。- no_match_size
- 一致するフラグメントがない場合にフィールドの先頭から返したいテキストの量。デフォルトは 0(何も返されません)。
- number_of_fragments
- 返すフラグメントの最大数。フラグメント数が 0 に設定されている場合、フラグメントは返されません。代わりに、フィールドの全内容がハイライトされて返されます。これは、タイトルや住所などの短いテキストをハイライトする必要がある場合に便利ですが、断片化は必要ありません。
number_of_fragments
が 0 の場合、fragment_size
は無視されます。デフォルトは 5 です。 - order
score
に設定すると、スコアによってハイライトされたフラグメントがソートされます。デフォルトでは、フラグメントはフィールドに表示される順序で出力されます(順序:none
)。このオプションをscore
に設定すると、最も関連性の高いフラグメントが最初に出力されます。各ハイライターは、関連性スコアを計算するための独自のロジックを適用します。異なるハイライターが最良のフラグメントを見つける方法の詳細については、ドキュメント ハイライターが内部でどのように機能するか を参照してください。- phrase_limit
- 文書内で考慮される一致するフレーズの数を制御します。
fvh
ハイライターがあまりにも多くのフレーズを分析して過剰なメモリを消費するのを防ぎます。matched_fields
を使用する場合、各一致フィールドに対してphrase_limit
フレーズが考慮されます。制限を上げると、クエリ時間が増加し、メモリを多く消費します。fvh
ハイライターでのみサポートされています。デフォルトは 256 です。 - pre_tags
- ハイライトされたテキストに使用する HTML タグを定義するために
post_tags
と組み合わせて使用します。デフォルトでは、ハイライトされたテキストは<em>
および</em>
タグでラップされます。文字列の配列として指定します。 - post_tags
- ハイライトされたテキストに使用する HTML タグを定義するために
pre_tags
と組み合わせて使用します。デフォルトでは、ハイライトされたテキストは<em>
および</em>
タグでラップされます。文字列の配列として指定します。 - require_field_match
- デフォルトでは、クエリ一致を含むフィールドのみがハイライトされます。すべてのフィールドをハイライトするには、
require_field_match
をfalse
に設定します。デフォルトはtrue
です。
- max_analyzed_offset
- デフォルトでは、ハイライトリクエストの分析される最大文字数は、
index.highlight.max_analyzed_offset
設定で定義された値によって制限されており、文字数がこの制限を超えるとエラーが返されます。この設定が非負の値に設定されている場合、ハイライトはこの定義された最大制限で停止し、残りのテキストは処理されず、したがってハイライトされず、エラーも返されません。max_analyzed_offset
クエリ設定は、index.highlight.max_analyzed_offset
をオーバーライドしません。クエリ設定よりも低い値に設定されている場合は、index.highlight.max_analyzed_offset
が優先されます。 - tags_schema
- ビルトインタグスキーマを使用するには
styled
に設定します。styled
スキーマは、次のpre_tags
を定義し、post_tags
を</em>
として定義します。
Html
<em class="hlt1">, <em class="hlt2">, <em class="hlt3">,
<em class="hlt4">, <em class="hlt5">, <em class="hlt6">,
<em class="hlt7">, <em class="hlt8">, <em class="hlt9">,
<em class="hlt10">
- type
- 使用するハイライター:
unified
、plain
、またはfvh
。デフォルトはunified
です。
ハイライトの例
- グローバル設定をオーバーライド
- ハイライトクエリを指定
- ハイライタータイプを設定
- ハイライトタグを構成
- すべてのフィールドをハイライト
- 複数フィールドの一致を組み合わせる
- ハイライトされたフィールドを明示的に順序付ける
- ハイライトされたフラグメントを制御
- 投稿リストを使用してハイライト
- プレーンハイライターのためのフラグメンターを指定
グローバル設定をオーバーライド
ハイライター設定をグローバルに指定し、個々のフィールドに対して選択的にオーバーライドできます。
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"number_of_fragments": 3,
"fragment_size": 150,
"fields": {
"body": {
"pre_tags": [
"<em>"
],
"post_tags": [
"</em>"
]
},
"blog.title": {
"number_of_fragments": 0
},
"blog.author": {
"number_of_fragments": 0
},
"blog.comment": {
"number_of_fragments": 5,
"order": "score"
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
number_of_fragments: 3,
fragment_size: 150,
fields: {
body: {
pre_tags: [
'<em>'
],
post_tags: [
'</em>'
]
},
'blog.title' => {
number_of_fragments: 0
},
'blog.author' => {
number_of_fragments: 0
},
'blog.comment' => {
number_of_fragments: 5,
order: 'score'
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
number_of_fragments: 3,
fragment_size: 150,
fields: {
body: {
pre_tags: ["<em>"],
post_tags: ["</em>"],
},
"blog.title": {
number_of_fragments: 0,
},
"blog.author": {
number_of_fragments: 0,
},
"blog.comment": {
number_of_fragments: 5,
order: "score",
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"number_of_fragments" : 3,
"fragment_size" : 150,
"fields" : {
"body" : { "pre_tags" : ["<em>"], "post_tags" : ["</em>"] },
"blog.title" : { "number_of_fragments" : 0 },
"blog.author" : { "number_of_fragments" : 0 },
"blog.comment" : { "number_of_fragments" : 5, "order" : "score" }
}
}
}
ハイライトクエリを指定
ハイライト時に追加情報を考慮するために highlight_query
を指定できます。たとえば、次のクエリは、highlight_query
に検索クエリとリスコアクエリの両方を含みます。highlight_query
がない場合、ハイライトは検索クエリのみを考慮します。
Python
resp = client.search(
query={
"match": {
"comment": {
"query": "foo bar"
}
}
},
rescore={
"window_size": 50,
"query": {
"rescore_query": {
"match_phrase": {
"comment": {
"query": "foo bar",
"slop": 1
}
}
},
"rescore_query_weight": 10
}
},
source=False,
highlight={
"order": "score",
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3,
"highlight_query": {
"bool": {
"must": {
"match": {
"comment": {
"query": "foo bar"
}
}
},
"should": {
"match_phrase": {
"comment": {
"query": "foo bar",
"slop": 1,
"boost": 10
}
}
},
"minimum_should_match": 0
}
}
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
comment: {
query: 'foo bar'
}
}
},
rescore: {
window_size: 50,
query: {
rescore_query: {
match_phrase: {
comment: {
query: 'foo bar',
slop: 1
}
}
},
rescore_query_weight: 10
}
},
_source: false,
highlight: {
order: 'score',
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
highlight_query: {
bool: {
must: {
match: {
comment: {
query: 'foo bar'
}
}
},
should: {
match_phrase: {
comment: {
query: 'foo bar',
slop: 1,
boost: 10
}
}
},
minimum_should_match: 0
}
}
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
comment: {
query: "foo bar",
},
},
},
rescore: {
window_size: 50,
query: {
rescore_query: {
match_phrase: {
comment: {
query: "foo bar",
slop: 1,
},
},
},
rescore_query_weight: 10,
},
},
_source: false,
highlight: {
order: "score",
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
highlight_query: {
bool: {
must: {
match: {
comment: {
query: "foo bar",
},
},
},
should: {
match_phrase: {
comment: {
query: "foo bar",
slop: 1,
boost: 10,
},
},
},
minimum_should_match: 0,
},
},
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query": {
"match": {
"comment": {
"query": "foo bar"
}
}
},
"rescore": {
"window_size": 50,
"query": {
"rescore_query": {
"match_phrase": {
"comment": {
"query": "foo bar",
"slop": 1
}
}
},
"rescore_query_weight": 10
}
},
"_source": false,
"highlight": {
"order": "score",
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3,
"highlight_query": {
"bool": {
"must": {
"match": {
"comment": {
"query": "foo bar"
}
}
},
"should": {
"match_phrase": {
"comment": {
"query": "foo bar",
"slop": 1,
"boost": 10.0
}
}
},
"minimum_should_match": 0
}
}
}
}
}
}
ハイライタータイプを設定
type
フィールドは、特定のハイライタータイプを強制することを可能にします。許可される値は、unified
、plain
、および fvh
です。次の例は、プレーンハイライターの使用を強制するものです:
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"fields": {
"comment": {
"type": "plain"
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
fields: {
comment: {
type: 'plain'
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
fields: {
comment: {
type: "plain",
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query": {
"match": { "user.id": "kimchy" }
},
"highlight": {
"fields": {
"comment": { "type": "plain" }
}
}
}
ハイライトタグを構成
デフォルトでは、ハイライトはハイライトされたテキストを <em>
および </em>
でラップします。これは、pre_tags
および post_tags
を設定することで制御できます。たとえば:
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"pre_tags": [
"<tag1>"
],
"post_tags": [
"</tag1>"
],
"fields": {
"body": {}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
pre_tags: [
'<tag1>'
],
post_tags: [
'</tag1>'
],
fields: {
body: {}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
pre_tags: ["<tag1>"],
post_tags: ["</tag1>"],
fields: {
body: {},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"pre_tags" : ["<tag1>"],
"post_tags" : ["</tag1>"],
"fields" : {
"body" : {}
}
}
}
ファストベクターハイライターを使用する場合、追加のタグを指定でき、”重要度” が順序付けられます。
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"pre_tags": [
"<tag1>",
"<tag2>"
],
"post_tags": [
"</tag1>",
"</tag2>"
],
"fields": {
"body": {}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
pre_tags: [
'<tag1>',
'<tag2>'
],
post_tags: [
'</tag1>',
'</tag2>'
],
fields: {
body: {}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
pre_tags: ["<tag1>", "<tag2>"],
post_tags: ["</tag1>", "</tag2>"],
fields: {
body: {},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"pre_tags" : ["<tag1>", "<tag2>"],
"post_tags" : ["</tag1>", "</tag2>"],
"fields" : {
"body" : {}
}
}
}
ビルトイン styled
タグスキーマを使用することもできます:
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"tags_schema": "styled",
"fields": {
"comment": {}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
tags_schema: 'styled',
fields: {
comment: {}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
tags_schema: "styled",
fields: {
comment: {},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"tags_schema" : "styled",
"fields" : {
"comment" : {}
}
}
}
すべてのフィールドでハイライト
デフォルトでは、クエリ一致を含むフィールドのみがハイライトされます。require_field_match
を false
に設定すると、すべてのフィールドがハイライトされます。
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"require_field_match": False,
"fields": {
"body": {
"pre_tags": [
"<em>"
],
"post_tags": [
"</em>"
]
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
require_field_match: false,
fields: {
body: {
pre_tags: [
'<em>'
],
post_tags: [
'</em>'
]
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
require_field_match: false,
fields: {
body: {
pre_tags: ["<em>"],
post_tags: ["</em>"],
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"require_field_match": false,
"fields": {
"body" : { "pre_tags" : ["<em>"], "post_tags" : ["</em>"] }
}
}
}
複数フィールドの一致を組み合わせる
unified
および fvh
ハイライターでサポートされています。
統一ハイライターとファストベクターハイライターは、複数のフィールドの一致を組み合わせて単一のフィールドをハイライトできます。これは、同じ文字列を異なる方法で分析するマルチフィールドに最も直感的です。
次の例では、comment
が standard
アナライザーによって分析され、comment.english
が english
アナライザーによって分析されます。
Python
resp = client.indices.create(
index="index1",
mappings={
"properties": {
"comment": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
},
)
print(resp)
Js
const response = await client.indices.create({
index: "index1",
mappings: {
properties: {
comment: {
type: "text",
analyzer: "standard",
fields: {
english: {
type: "text",
analyzer: "english",
},
},
},
},
},
});
console.log(response);
コンソール
PUT index1
{
"mappings": {
"properties": {
"comment": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}
Python
resp = client.bulk(
index="index1",
refresh=True,
operations=[
{
"index": {
"_id": "doc1"
}
},
{
"comment": "run with scissors"
},
{
"index": {
"_id": "doc2"
}
},
{
"comment": "running with scissors"
}
],
)
print(resp)
Js
const response = await client.bulk({
index: "index1",
refresh: "true",
operations: [
{
index: {
_id: "doc1",
},
},
{
comment: "run with scissors",
},
{
index: {
_id: "doc2",
},
},
{
comment: "running with scissors",
},
],
});
console.log(response);
コンソール
PUT index1/_bulk?refresh=true
{"index": {"_id": "doc1" }}
{"comment": "run with scissors"}
{ "index" : {"_id": "doc2"} }
{"comment": "running with scissors"}
Python
resp = client.search(
index="index1",
query={
"query_string": {
"query": "running with scissors",
"fields": [
"comment",
"comment.english"
]
}
},
highlight={
"order": "score",
"fields": {
"comment": {}
}
},
)
print(resp)
Js
const response = await client.search({
index: "index1",
query: {
query_string: {
query: "running with scissors",
fields: ["comment", "comment.english"],
},
},
highlight: {
order: "score",
fields: {
comment: {},
},
},
});
console.log(response);
コンソール
GET index1/_search
{
"query": {
"query_string": {
"query": "running with scissors",
"fields": ["comment", "comment.english"]
}
},
"highlight": {
"order": "score",
"fields": {
"comment": {}
}
}
}
上記のリクエストは「ハサミで走る」と「ハサミで走る」を両方一致させ、「走っている」と「ハサミ」をハイライトしますが、「走る」はハイライトしません。両方のフレーズが大きな文書に出現する場合、「ハサミで走っている」がフラグメントリストで「ハサミで走る」よりも上にソートされます。なぜなら、そのフラグメントに一致が多いからです。
コンソール-結果
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score": 1.0577903,
"hits" : [
{
"_index" : "index1",
"_id" : "doc2",
"_score" : 1.0577903,
"_source" : {
"comment" : "running with scissors"
},
"highlight" : {
"comment" : [
"<em>running</em> <em>with</em> <em>scissors</em>"
]
}
},
{
"_index" : "index1",
"_id" : "doc1",
"_score" : 0.36464313,
"_source" : {
"comment" : "run with scissors"
},
"highlight" : {
"comment" : [
"run <em>with</em> <em>scissors</em>"
]
}
}
]
}
}
以下のリクエストは「走る」と「走っている」と「ハサミ」をハイライトします。なぜなら、matched_fields
パラメータが、ハイライトのために comment.english
フィールドの一致を元の comment
フィールドの一致と組み合わせる必要があることを指示しているからです。
Python
resp = client.search(
index="index1",
query={
"query_string": {
"query": "running with scissors",
"fields": [
"comment",
"comment.english"
]
}
},
highlight={
"order": "score",
"fields": {
"comment": {
"matched_fields": [
"comment.english"
]
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "index1",
query: {
query_string: {
query: "running with scissors",
fields: ["comment", "comment.english"],
},
},
highlight: {
order: "score",
fields: {
comment: {
matched_fields: ["comment.english"],
},
},
},
});
console.log(response);
コンソール
GET index1/_search
{
"query": {
"query_string": {
"query": "running with scissors",
"fields": ["comment", "comment.english"]
}
},
"highlight": {
"order": "score",
"fields": {
"comment": {
"matched_fields": ["comment.english"]
}
}
}
}
コンソール-結果
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score": 1.0577903,
"hits" : [
{
"_index" : "index1",
"_id" : "doc2",
"_score" : 1.0577903,
"_source" : {
"comment" : "running with scissors"
},
"highlight" : {
"comment" : [
"<em>running</em> <em>with</em> <em>scissors</em>"
]
}
},
{
"_index" : "index1",
"_id" : "doc1",
"_score" : 0.36464313,
"_source" : {
"comment" : "run with scissors"
},
"highlight" : {
"comment" : [
"<em>run</em> <em>with</em> <em>scissors</em>"
]
}
}
]
}
}
次の例では、comment
が standard
アナライザーによって分析され、comment.english
が english
アナライザーによって分析されます。
Python
resp = client.indices.create(
index="index2",
mappings={
"properties": {
"comment": {
"type": "text",
"analyzer": "standard",
"term_vector": "with_positions_offsets",
"fields": {
"english": {
"type": "text",
"analyzer": "english",
"term_vector": "with_positions_offsets"
}
}
}
}
},
)
print(resp)
Js
const response = await client.indices.create({
index: "index2",
mappings: {
properties: {
comment: {
type: "text",
analyzer: "standard",
term_vector: "with_positions_offsets",
fields: {
english: {
type: "text",
analyzer: "english",
term_vector: "with_positions_offsets",
},
},
},
},
},
});
console.log(response);
コンソール
PUT index2
{
"mappings": {
"properties": {
"comment": {
"type": "text",
"analyzer": "standard",
"term_vector": "with_positions_offsets",
"fields": {
"english": {
"type": "text",
"analyzer": "english",
"term_vector": "with_positions_offsets"
}
}
}
}
}
}
Python
resp = client.bulk(
index="index2",
refresh=True,
operations=[
{
"index": {
"_id": "doc1"
}
},
{
"comment": "run with scissors"
},
{
"index": {
"_id": "doc2"
}
},
{
"comment": "running with scissors"
}
],
)
print(resp)
Js
const response = await client.bulk({
index: "index2",
refresh: "true",
operations: [
{
index: {
_id: "doc1",
},
},
{
comment: "run with scissors",
},
{
index: {
_id: "doc2",
},
},
{
comment: "running with scissors",
},
],
});
console.log(response);
コンソール
PUT index2/_bulk?refresh=true
{"index": {"_id": "doc1" }}
{"comment": "run with scissors"}
{ "index" : {"_id": "doc2"} }
{"comment": "running with scissors"}
Python
resp = client.search(
index="index2",
query={
"query_string": {
"query": "running with scissors",
"fields": [
"comment",
"comment.english"
]
}
},
highlight={
"order": "score",
"fields": {
"comment": {
"type": "fvh"
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "index2",
query: {
query_string: {
query: "running with scissors",
fields: ["comment", "comment.english"],
},
},
highlight: {
order: "score",
fields: {
comment: {
type: "fvh",
},
},
},
});
console.log(response);
コンソール
GET index2/_search
{
"query": {
"query_string": {
"query": "running with scissors",
"fields": ["comment", "comment.english"]
}
},
"highlight": {
"order": "score",
"fields": {
"comment": {
"type" : "fvh"
}
}
}
}
上記のリクエストは「ハサミで走る」と「ハサミで走る」を両方一致させ、「走っている」と「ハサミ」をハイライトしますが、「走る」はハイライトしません。両方のフレーズが大きな文書に出現する場合、「ハサミで走っている」がフラグメントリストで「ハサミで走る」よりも上にソートされます。なぜなら、そのフラグメントに一致が多いからです。
コンソール-結果
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score": 1.0577903,
"hits" : [
{
"_index" : "index2",
"_id" : "doc2",
"_score" : 1.0577903,
"_source" : {
"comment" : "running with scissors"
},
"highlight" : {
"comment" : [
"<em>running</em> <em>with</em> <em>scissors</em>"
]
}
},
{
"_index" : "index2",
"_id" : "doc1",
"_score" : 0.36464313,
"_source" : {
"comment" : "run with scissors"
},
"highlight" : {
"comment" : [
"run <em>with</em> <em>scissors</em>"
]
}
}
]
}
}
以下のリクエストは「走る」や「ハサミ」をハイライトしませんが、一致が組み合わされるフィールド(matched_fields
)を一致フィールドにリストしないことが問題ないことを示しています。
Python
resp = client.search(
index="index2",
query={
"query_string": {
"query": "running with scissors",
"fields": [
"comment",
"comment.english"
]
}
},
highlight={
"order": "score",
"fields": {
"comment": {
"type": "fvh",
"matched_fields": [
"comment",
"comment.english"
]
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "index2",
query: {
query_string: {
query: "running with scissors",
fields: ["comment", "comment.english"],
},
},
highlight: {
order: "score",
fields: {
comment: {
type: "fvh",
matched_fields: ["comment", "comment.english"],
},
},
},
});
console.log(response);
コンソール
GET index2/_search
{
"query": {
"query_string": {
"query": "running with scissors",
"fields": ["comment", "comment.english"]
}
},
"highlight": {
"order": "score",
"fields": {
"comment": {
"type" : "fvh",
"matched_fields": ["comment", "comment.english"]
}
}
}
}
コンソール-結果
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score": 1.0577903,
"hits" : [
{
"_index" : "index2",
"_id" : "doc2",
"_score" : 1.0577903,
"_source" : {
"comment" : "running with scissors"
},
"highlight" : {
"comment" : [
"<em>running</em> <em>with</em> <em>scissors</em>"
]
}
},
{
"_index" : "index2",
"_id" : "doc1",
"_score" : 0.36464313,
"_source" : {
"comment" : "run with scissors"
},
"highlight" : {
"comment" : [
"<em>run</em> <em>with</em> <em>scissors</em>"
]
}
}
]
}
}
以下のリクエストは「走る」や「ハサミ」をハイライトしませんが、一致が組み合わされるフィールド(comment.english
)を一致フィールドにリストしないことが問題ないことを示しています。
Python
resp = client.search(
index="index2",
query={
"query_string": {
"query": "running with scissors",
"fields": [
"comment",
"comment.english"
]
}
},
highlight={
"order": "score",
"fields": {
"comment.english": {
"type": "fvh",
"matched_fields": [
"comment"
]
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "index2",
query: {
query_string: {
query: "running with scissors",
fields: ["comment", "comment.english"],
},
},
highlight: {
order: "score",
fields: {
"comment.english": {
type: "fvh",
matched_fields: ["comment"],
},
},
},
});
console.log(response);
コンソール
GET index2/_search
{
"query": {
"query_string": {
"query": "running with scissors",
"fields": ["comment", "comment.english"]
}
},
"highlight": {
"order": "score",
"fields": {
"comment.english": {
"type" : "fvh",
"matched_fields": ["comment"]
}
}
}
}
コンソール-結果
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score": 1.0577903,
"hits" : [
{
"_index" : "index2",
"_id" : "doc2",
"_score" : 1.0577903,
"_source" : {
"comment" : "running with scissors"
},
"highlight" : {
"comment.english" : [
"<em>running</em> <em>with</em> <em>scissors</em>"
]
}
},
{
"_index" : "index2",
"_id" : "doc1",
"_score" : 0.36464313,
"_source" : {
"comment" : "run with scissors"
},
"highlight" : {
"comment.english" : [
"run <em>with</em> <em>scissors</em>"
]
}
}
]
}
}
matched_fields
を非空配列に設定することには少しオーバーヘッドがあるため、常にmatched_fields
を使用することをお勧めします。
Js
"highlight": {
"fields": {
"comment": {}
}
}
to
Js
"highlight": {
"fields": {
"comment": {
"matched_fields": ["comment"],
"type" : "fvh"
}
}
}
技術的には、一致が組み合わされるフィールドと同じ基盤の文字列を共有しないフィールドを matched_fields
に追加することも問題ありません。結果はあまり意味をなさないかもしれませんし、一致の1つがテキストの端を超えている場合、全体のクエリが失敗します。
ハイライトされたフィールドの明示的な順序
Elasticsearch は、送信された順序でフィールドをハイライトしますが、JSON スペックに従って、オブジェクトは順序がありません。フィールドがハイライトされる順序を明示的に指定する必要がある場合は、fields
を配列として指定します:
Python
resp = client.search(
highlight={
"fields": [
{
"title": {}
},
{
"text": {}
}
]
},
)
print(resp)
Ruby
response = client.search(
body: {
highlight: {
fields: [
{
title: {}
},
{
text: {}
}
]
}
}
)
puts response
Js
const response = await client.search({
highlight: {
fields: [
{
title: {},
},
{
text: {},
},
],
},
});
console.log(response);
コンソール
GET /_search
{
"highlight": {
"fields": [
{ "title": {} },
{ "text": {} }
]
}
}
Elasticsearch に組み込まれているハイライターは、フィールドがハイライトされる順序を気にしませんが、プラグインは気にするかもしれません。
ハイライトされたフラグメントを制御
ハイライトされた各フィールドは、ハイライトされたフラグメントのサイズを文字数で制御できます(デフォルトは 100
)、および返すフラグメントの最大数(デフォルトは 5
)。たとえば:
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"fields" : {
"comment" : {"fragment_size" : 150, "number_of_fragments" : 3}
}
}
}
この上に、ハイライトされたフラグメントをスコアでソートする必要があることを指定することも可能です:
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"order": "score",
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
order: 'score',
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
order: "score",
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"order" : "score",
"fields" : {
"comment" : {"fragment_size" : 150, "number_of_fragments" : 3}
}
}
}
number_of_fragments
値が 0
に設定されている場合、フラグメントは生成されず、代わりにフィールドの全内容が返され、もちろんハイライトされます。これは、短いテキスト(文書のタイトルや住所など)をハイライトする必要がある場合に非常に便利ですが、断片化は必要ありません。この場合、fragment_size
は無視されます。
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"fields": {
"body": {},
"blog.title": {
"number_of_fragments": 0
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
fields: {
body: {},
'blog.title' => {
number_of_fragments: 0
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
fields: {
body: {},
"blog.title": {
number_of_fragments: 0,
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query" : {
"match": { "user.id": "kimchy" }
},
"highlight" : {
"fields" : {
"body" : {},
"blog.title" : {"number_of_fragments" : 0}
}
}
}
fvh
を使用する場合、ハイライトを開始するマージンを制御するために fragment_offset
パラメータを使用できます。
一致するフラグメントがない場合のデフォルトは、何も返さないことです。代わりに、no_match_size
(デフォルト 0
)を設定することで、返したいテキストの長さに基づいてフィールドの先頭からテキストのスニペットを返すことができます。実際の長さは、単語の境界で分割しようとするため、指定された長さよりも短くなる場合や長くなる場合があります。
Python
resp = client.search(
query={
"match": {
"user.id": "kimchy"
}
},
highlight={
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3,
"no_match_size": 150
}
}
},
)
print(resp)
Ruby
response = client.search(
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
highlight: {
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
no_match_size: 150
}
}
}
}
)
puts response
Js
const response = await client.search({
query: {
match: {
"user.id": "kimchy",
},
},
highlight: {
fields: {
comment: {
fragment_size: 150,
number_of_fragments: 3,
no_match_size: 150,
},
},
},
});
console.log(response);
コンソール
GET /_search
{
"query": {
"match": { "user.id": "kimchy" }
},
"highlight": {
"fields": {
"comment": {
"fragment_size": 150,
"number_of_fragments": 3,
"no_match_size": 150
}
}
}
}
投稿リストを使用してハイライト
ここでは、投稿を使用してハイライトを許可するためにインデックスマッピングで comment
フィールドを設定する例を示します:
Python
resp = client.indices.create(
index="example",
mappings={
"properties": {
"comment": {
"type": "text",
"index_options": "offsets"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'example',
body: {
mappings: {
properties: {
comment: {
type: 'text',
index_options: 'offsets'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "example",
mappings: {
properties: {
comment: {
type: "text",
index_options: "offsets",
},
},
},
});
console.log(response);
コンソール
PUT /example
{
"mappings": {
"properties": {
"comment" : {
"type": "text",
"index_options" : "offsets"
}
}
}
}
ここでは、comment
フィールドを設定して term_vectors
を使用してハイライトを許可する例を示します(これによりインデックスが大きくなります):
Python
resp = client.indices.create(
index="example",
mappings={
"properties": {
"comment": {
"type": "text",
"term_vector": "with_positions_offsets"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'example',
body: {
mappings: {
properties: {
comment: {
type: 'text',
term_vector: 'with_positions_offsets'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "example",
mappings: {
properties: {
comment: {
type: "text",
term_vector: "with_positions_offsets",
},
},
},
});
console.log(response);
コンソール
PUT /example
{
"mappings": {
"properties": {
"comment" : {
"type": "text",
"term_vector" : "with_positions_offsets"
}
}
}
}
プレーンハイライターのためのフラグメンターを指定
plain
ハイライターを使用する場合、simple
および span
フラグメンターの間で選択できます:
Python
resp = client.search(
index="my-index-000001",
query={
"match_phrase": {
"message": "number 1"
}
},
highlight={
"fields": {
"message": {
"type": "plain",
"fragment_size": 15,
"number_of_fragments": 3,
"fragmenter": "simple"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
query: {
match_phrase: {
message: 'number 1'
}
},
highlight: {
fields: {
message: {
type: 'plain',
fragment_size: 15,
number_of_fragments: 3,
fragmenter: 'simple'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
query: {
match_phrase: {
message: "number 1",
},
},
highlight: {
fields: {
message: {
type: "plain",
fragment_size: 15,
number_of_fragments: 3,
fragmenter: "simple",
},
},
},
});
console.log(response);
Console
GET my-index-000001/_search
{
"query": {
"match_phrase": { "message": "number 1" }
},
"highlight": {
"fields": {
"message": {
"type": "plain",
"fragment_size": 15,
"number_of_fragments": 3,
"fragmenter": "simple"
}
}
}
}
Console-Result
{
...
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.6011951,
"hits": [
{
"_index": "my-index-000001",
"_id": "1",
"_score": 1.6011951,
"_source": {
"message": "some message with the number 1",
"context": "bar"
},
"highlight": {
"message": [
" with the <em>number</em>",
" <em>1</em>"
]
}
}
]
}
}
Python
resp = client.search(
index="my-index-000001",
query={
"match_phrase": {
"message": "number 1"
}
},
highlight={
"fields": {
"message": {
"type": "plain",
"fragment_size": 15,
"number_of_fragments": 3,
"fragmenter": "span"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
query: {
match_phrase: {
message: 'number 1'
}
},
highlight: {
fields: {
message: {
type: 'plain',
fragment_size: 15,
number_of_fragments: 3,
fragmenter: 'span'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
query: {
match_phrase: {
message: "number 1",
},
},
highlight: {
fields: {
message: {
type: "plain",
fragment_size: 15,
number_of_fragments: 3,
fragmenter: "span",
},
},
},
});
console.log(response);
Console
GET my-index-000001/_search
{
"query": {
"match_phrase": { "message": "number 1" }
},
"highlight": {
"fields": {
"message": {
"type": "plain",
"fragment_size": 15,
"number_of_fragments": 3,
"fragmenter": "span"
}
}
}
}
Console-Result
{
...
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.6011951,
"hits": [
{
"_index": "my-index-000001",
"_id": "1",
"_score": 1.6011951,
"_source": {
"message": "some message with the number 1",
"context": "bar"
},
"highlight": {
"message": [
" with the <em>number</em> <em>1</em>"
]
}
}
]
}
}
#### ハイライターの内部動作
クエリとテキスト(ドキュメントフィールドの内容)が与えられた場合、ハイライターの目的は、クエリに対して最適なテキストの断片を見つけ、見つかった断片内のクエリ用語を強調表示することです。これには、ハイライターがいくつかの質問に対処する必要があります:
- テキストをどのように断片に分割するか?
- すべての断片の中から最適な断片をどのように見つけるか?
- 断片内のクエリ用語をどのように強調表示するか?
## テキストをどのように断片に分割するか?
関連設定:`````fragment_size`````、`````fragmenter`````、`````type`````のハイライター、`````boundary_chars`````、`````boundary_max_scan`````、`````boundary_scanner`````、`````boundary_scanner_locale`````。
プレーンハイライターは、与えられたアナライザーを使用してテキストを分析し、トークンストリームを作成することから始まります。プレーンハイライターは、トークンストリームを断片に分割するために非常に単純なアルゴリズムを使用します。トークンストリーム内の用語をループし、現在の用語のend_offsetが`````fragment_size`````に作成された断片の数を掛けた値を超えるたびに、新しい断片が作成されます。ハイライトされた用語の間でテキストが分割されないようにするために、`````span`````フラグメンターを使用してもう少し計算が行われます。しかし、全体として、分割は`````fragment_size`````によってのみ行われるため、いくつかの断片は非常に奇妙なものになる可能性があります。たとえば、句読点で始まるものです。
統一またはFVHハイライターは、Javaの`````BreakIterator`````を利用してテキストを断片に分割するのが得意です。これにより、`````fragment_size`````が許可されている限り、断片が有効な文であることが保証されます。
## 最適な断片をどのように見つけるか?
関連設定:`````number_of_fragments`````。
最適で最も関連性の高い断片を見つけるために、ハイライターは与えられたクエリに対して各断片にスコアを付ける必要があります。目標は、ドキュメントの*ヒット*を生成するのに参加した用語のみをスコアリングすることです。いくつかの複雑なクエリに対しては、これはまだ進行中の作業です。
プレーンハイライターは、現在のトークンストリームからメモリ内インデックスを作成し、Luceneのクエリ実行プランナーを通じて元のクエリ基準を再実行して、現在のテキストの低レベルの一致情報にアクセスします。より複雑なクエリの場合、元のクエリはスパンクエリに変換される可能性があります。スパンクエリはフレーズをより正確に処理できます。この取得した低レベルの一致情報を使用して、各個別の断片にスコアを付けます。プレーンハイライターのスコアリング方法は非常に単純です。各断片は、この断片内で見つかったユニークなクエリ用語の数によってスコアが付けられます。個々の用語のスコアは、そのブーストに等しく、デフォルトでは1です。したがって、デフォルトでは、1つのユニークなクエリ用語を含む断片はスコア1を取得し、2つのユニークなクエリ用語を含む断片はスコア2を取得します。断片はそのスコアによってソートされ、最も高いスコアの断片が最初に出力されます。
FVHは、テキストを分析してメモリ内インデックスを構築する必要がなく、事前にインデックスされたドキュメント用語ベクトルを使用し、それらの中からクエリに対応する用語を見つけます。FVHは、各断片に見つかったクエリ用語の数によってスコアを付けます。プレーンハイライターと同様に、個々の用語のスコアはそのブースト値に等しいです。プレーンハイライターとは対照的に、すべてのクエリ用語がカウントされ、ユニークな用語だけではありません。
統一ハイライターは、事前にインデックスされた用語ベクトルまたは事前にインデックスされた用語オフセットを使用できます。利用可能な場合は、そうでなければ、プレーンハイライターと同様に、テキストからメモリ内インデックスを作成する必要があります。統一ハイライターは、断片にスコアを付けるためにBM25スコアリングモデルを使用します。
## 断片内のクエリ用語をどのように強調表示するか?
関連設定:`````pre-tags`````、`````post-tags`````。
目標は、ドキュメントの*ヒット*を生成するのに参加した用語のみを強調表示することです。いくつかの複雑なブールクエリに対しては、これはまだ進行中の作業です。ハイライターはクエリのブールロジックを反映せず、葉(用語、フレーズ、接頭辞など)クエリのみを抽出します。
プレーンハイライターは、トークンストリームと元のテキストを与えられた場合、元のテキストを再構成して、前のステップからの低レベルの一致情報構造に含まれるトークンストリームの用語のみを強調表示します。
FVHと統一ハイライターは、いくつかの生の形式で断片を表す中間データ構造を使用し、実際のテキストでそれらを埋めます。
ハイライターは、`````pre-tags`````、`````post-tags`````を使用して強調表示された用語をエンコードします。
## 統一ハイライターの作業の例
統一ハイライターがどのように機能するかを詳しく見てみましょう。
まず、`````content`````というテキストフィールドを持つインデックスを作成します。これは、`````english`````アナライザーを使用してインデックスされ、オフセットや用語ベクトルなしでインデックスされます。
#### Js
``````js
PUT test_index
{
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "english"
}
}
}
}
`
次のドキュメントをインデックスに追加します:
Js
PUT test_index/_doc/doc1
{
"content" : "For you I'm only a fox like a hundred thousand other foxes. But if you tame me, we'll need each other. You'll be the only boy in the world for me. I'll be the only fox in the world for you."
}
次のクエリをハイライトリクエストで実行しました:
Js
GET test_index/_search
{
"query": {
"match_phrase" : {"content" : "only fox"}
},
"highlight": {
"type" : "unified",
"number_of_fragments" : 3,
"fields": {
"content": {}
}
}
}
``````bash
{"token":"onli","start_offset":12,"end_offset":16,"position":3},
{"token":"fox","start_offset":19,"end_offset":22,"position":5},
{"token":"fox","start_offset":53,"end_offset":58,"position":11},
{"token":"onli","start_offset":117,"end_offset":121,"position":24},
{"token":"onli","start_offset":159,"end_offset":163,"position":34},
{"token":"fox","start_offset":164,"end_offset":167,"position":35}
`
私たちの複雑なフレーズクエリはスパンクエリに変換されます:spanNear([text:onli, text:fox], 0, true)
、これは「onli」と「fox」という用語が互いに0距離以内で、指定された順序であることを意味します。スパンクエリは、以前に作成されたメモリ内インデックスに対して実行され、次の一致を見つけます:
{"term":"onli", "start_offset":159, "end_offset":163},
{"term":"fox", "start_offset":164, "end_offset":167}
私たちの例では、単一の一致が得られましたが、複数の一致がある可能性があります。一致が得られると、統一ハイライターはフィールドのテキストを「パッセージ」と呼ばれるものに分割します。各パッセージには少なくとも1つの一致が含まれている必要があります。統一ハイライターは、JavaのBreakIterator
を使用して、各パッセージがfragment_size
を超えない限り、完全な文を表すことを保証します。私たちの例では、次のプロパティを持つ単一のパッセージが得られました(ここではプロパティのサブセットのみを示しています):
Passage:
startOffset: 147
endOffset: 189
score: 3.7158387
matchStarts: [159, 164]
matchEnds: [163, 167]
numMatches: 2
パッセージにはスコアがあり、これはパッセージ用に適応されたBM25スコアリング式を使用して計算されます。スコアにより、ユーザーが要求したnumber_of_fragments
よりも多くのパッセージが利用可能な場合、最も高いスコアのパッセージを選択できます。スコアは、ユーザーが要求した場合、order: "score"
によってパッセージをソートすることも可能にします。
最後のステップとして、統一ハイライターはフィールドのテキストから各パッセージに対応する文字列を抽出します:
"I'll be the only fox in the world for you."
そして、すべての一致をこの文字列内で、パッセージのmatchStarts
およびmatchEnds
情報を使用して、およびタグでフォーマットします:
I'll be the <em>only</em> <em>fox</em> in the world for you.
このようにフォーマットされた文字列は、ユーザーに返されるハイライターの最終結果です。