本ドキュメントは、検索リニューアルにおける検索クエリ、検索対象カラム、検索条件、スコアリング、Traversal All 表示制御、および検証用パラメータの仕様を整理したものです。
本検索では、入力されたキーワードに対して複数の検索条件を組み合わせ、OpenSearch の _score をもとに検索結果を並べます。
さらに、作品・キャラクター・人物・会社ごとの人気指標や放映日などを補助スコアとして加算します。
このドキュメントは、デモページの各入力項目を調整しながら検索品質を検証するためのマニュアルでもあります。
各パラメータの詳細仕様は、必要に応じて OpenSearch 公式ドキュメントを参照してください。
画面右上にある検索ボックスによる検索に利用されます。
検索対象に all が指定された場合、複数カテゴリを横断して検索します。
対象カテゴリは以下です。
Traversal All では、全体スコア順のみで並べるのではなく、カテゴリごとの偏りを抑えるための表示制御を行います。
詳細は Traversal All を参照してください。
各画面にある詳細検索機能に利用されます。
advanced では検索対象に all は指定できません。
特定の index / category に対して検索します。
検索対象は主にタイトル・名称系フィールドです。
anime / manga など、タイトルを持つデータでは以下を対象にします。
title.originaltitle.entitle.alttitle.jatitle_localized.titlecharacter / people / company など、名称を持つデータでは以下のような name 系フィールドを対象にします。
name.originalname.enname.altname.janame.alternatives実際にどの field を使うかは index 定義に依存します。
デモページの条件別表示では、index ごとに本検索と同じ検索対象 field を使っているかを確認してください。
完全一致や前方一致では、analyzer の影響を抑えた .raw フィールドを利用します。
対象例:
title.original.rawtitle.en.rawtitle.alt.rawtitle.ja.rawtitle_localized.title.raw.raw は主に以下の用途で利用します。
例:
C++!+!.hack部分一致や入力途中の検索では、ngram 系フィールドを利用します。
対象例:
title.original.ngram
title.en.ngram
title.alt.ngram
title.ja.ngram
title_localized.title.ngram
title.original.edge_ngram
title.en.edge_ngram
title.alt.edge_ngram
title.ja.edge_ngram
title_localized.title.edge_ngram
3.x 検索では、基本的に query_string 用のサニタイズは行いません。
+ を \+ にする! を \! にする: を \: にする- を \- にする/ を \/ にする理由は、3.x 検索で主に使うクエリが以下であり、query_string 構文として解釈されないためです。
termprefixmatchmatch_phrasematch_phrase_prefixmulti_matchmatch_bool_prefixたとえば、C++ を検索する場合、検索語は c++ のまま扱います。
c\+\+ にすると、実データの token と一致しなくなる可能性があります。
検索ロジックは、複数の検索条件を組み合わせてスコアを算出します。
検索条件ごとに boost を設定でき、boost が高い条件ほど検索結果への影響が大きくなります。
また、boost が 0 の条件は検索クエリに含めません。
これにより、画面から検索条件をON/OFFしながら比較検証できます。
デモページでは、各検索条件を boost でON/OFFしながら検索結果を比較します。
boost > 0: その検索条件を使うboost = 0: その検索条件を使わないslop, minimum_should_match, max_expansions, fuzziness など: 条件の拾い方を調整するfield_boost: どの field を強く見るかを調整するscore boost: 人気度や日付など、テキスト一致以外の補助スコアを調整する入力されたテキストと完全一致するタイトルを検索します。
主に .raw フィールドに対して利用します。
例:
検索語: seitokai ni mo ana wa aru!
対象: title.original.raw
完全一致したタイトルを強く上げたい場合に利用します。
boost:term を大きくすると、完全一致が上位に出やすくなります。boost:term = 0 にすると、完全一致条件を使いません。.raw に入る token と検索語が一致しているかを確認してください。公式ドキュメント: term query
入力されたテキストから始まるタイトルを前方一致で検索します。
例:
検索語: seitoka
ヒット例: Seitokai ni mo Ana wa Aru!
.raw フィールドに対する prefix は、記号を含むタイトルにも比較的強いです。
例:
検索語: c++
ヒット例: C++ で始まるタイトル
ただし、prefix はフィールド先頭からの一致です。
タイトル途中に含まれる文字列は拾えません。
boost:prefix を上げると、先頭一致を強く評価します。boost:prefix = 0 にすると、prefix 条件を使いません。.raw に対する prefix は、C++ や !+! のような記号検索の保険として有効です。edge_ngram と役割が近いため、両方を同時に強くしすぎるとスコアが積み上がりやすくなります。公式ドキュメント: prefix query
入力されたテキストをフレーズ先頭一致で検索します。
例:
検索語: subarashii seka
ヒット例: Kono Subarashii Sekai ni Shukufuku wo!
特徴:
boost:phrase_prefix を上げると、語順を保った入力途中検索を強く評価します。max_expansions:phrase_prefix を設定すると、最後の語を prefix 展開する候補数を調整できます。入力されたテキストを N-gram 検索します。
入力されたテキストとタイトルを、それぞれ連続する文字列に分割し、部分的に一致するものを検索します。
例:
検索語: ras
ヒット例: Kono Subarashii Sekai ni Shukufuku wo!
ngram はタイトル途中の部分一致に強い一方で、広く拾いすぎる可能性があります。
そのため、通常は低めの boost で fallback 的に利用します。
minimum_should_match:ngram は、ngram で細かく分割された検索語のうち、どの程度一致していれば候補として残すかを調整する項目です。
言い換えると、ngram が広く拾いすぎるときに、少し厳しめにするための絞り込み設定です。
例:
検索語: seitokai
ngram token: sei, eit, ito, tok, oka, kai ...
このとき minimum_should_match を指定しないと、一部の token が一致しただけでも候補に残ることがあります。
minimum_should_match:ngram = 75% のようにすると、より多くの token が一致したものだけが残りやすくなります。
おすすめの使い方:
minimum_should_match:ngram を 60% や 75% にする公式ドキュメント: minimum_should_match
入力されたテキストを、タイトルの先頭からの N-gram として検索します。
例:
検索語: kono
ヒット例: Kono Subarashii Sekai ni Shukufuku wo!
edge_ngram は入力補完や先頭一致に向いています。
prefix と役割が近いため、比較検証しながら採用有無や boost を調整します。
minimum_should_match:edge_ngram は、edge_ngram 条件で生成された token のうち、どの程度一致していれば候補として残すかを調整する項目です。
より実用的には、入力途中検索で候補が多すぎるときに、候補を少し絞るための設定です。
例:
検索語: fullmetal alch
edge_ngram は先頭一致に強いため、入力途中の候補を多く拾います。
候補が多すぎる場合は minimum_should_match:edge_ngram = 75% のようにして、より多くの token が一致した候補を優先できます。
おすすめの使い方:
minimum_should_match:edge_ngram を 60% や 75% にする公式ドキュメント: minimum_should_match
入力されたテキストを、語順を保ったフレーズとして検索します。
例:
検索語: fullmetal alchemist
語順が一致しているタイトルを評価します。
slop を指定すると、語の間にどの程度のズレを許容するかを調整できます。
例:
slop = 0
完全に連続した語順のみ
slop = 2
語の間に多少のズレを許容
boost:match_phrase を上げると、語順が合うタイトルを上げやすくなります。slop:match_phrase を上げると、語の間に少し別の語が入っても拾いやすくなります。公式ドキュメント: match_phrase query
match_phrase に近い検索ですが、最後の語だけ前方一致として扱います。
例:
検索語: fullmetal alch
ヒット例: Fullmetal Alchemist
入力途中のフレーズ検索に向いています。
match_phrase_prefix にも slop を指定できます。
語順のズレをどの程度許容するかを検証できます。
最後の語を prefix 展開するときに、最大でいくつの候補語へ展開するかを指定します。
値を大きくすると recall は上がりますが、検索負荷やノイズが増える可能性があります。
boost:match_phrase_prefix を上げると、入力途中のフレーズ一致を強く評価します。slop:match_phrase_prefix で語順のズレを許容できます。max_expansions:match_phrase_prefix で最後の語の展開数を制御できます。max_expansions を上げ、候補が広がりすぎる場合は下げます。公式ドキュメント: match_phrase_prefix query
入力されたテキストを通常の全文検索として検索します。
現在の検証では、基本的に operator: and を利用します。
つまり、入力された語がすべて含まれるものを検索します。
例:
検索語: fullmetal alchemist
条件: fullmetal と alchemist の両方を含む
minimum_should_match を指定すると、すべての語を必須にせず、指定割合または指定数以上の語が一致すればヒットさせることができます。
例:
minimum_should_match = 75%
この場合、長い検索語で一部の語が一致しなくても候補に残りやすくなります。
UI上は以下のように切り替えます。
minimum_should_match が空欄
operator: and を利用minimum_should_match が入力済み
minimum_should_match を利用operator: and は付与しないこれにより、空欄に戻すだけで AND 検索へ戻せます。
minimum_should_match = 75% などを試します。minimum_should_match を入れると候補は増えますが、ノイズも増える可能性があります。公式ドキュメント: match query / minimum_should_match
入力された語を解析し、最後の語だけ prefix として扱う検索です。
例:
検索語: fullmetal alch
以下のような動きになります。
fullmetal: 通常一致
alch: prefix 一致
phrase_prefix より語順制約が緩く、入力補完系の検索として比較対象になります。
fuzziness を指定すると、タイプミスをある程度許容できます。
例:
AUTO
1
2
ただし、短い検索語や固有名詞ではノイズが増える可能性があるため、低い boost で検証することを推奨します。
fuzziness min length は、検索語が一定以上の長さの場合だけ fuzziness を有効にするための設定です。
おすすめの使い方:
nami のような短い語では fuzziness を使わない公式ドキュメント: match_bool_prefix query
各検索条件には boost を設定できます。
boost は検索条件の重要度を調整する値です。
例:
term の boost を大きくする
→ 完全一致をより上位に出しやすくする
ngram の boost を小さくする
→ 部分一致によるノイズを抑える
boost が 0 の検索条件は、クエリに含めません。
例:
boost:term = 0
この場合、term クエリは生成されません。
これにより、検索条件のON/OFFを画面から簡単に切り替えられます。
検索対象フィールドごとに重みを調整できます。
対象例:
title.originaltitle.entitle.alttitle.jatitle_localized.title例:
title.original = 1.0
title.en = 1.0
title.alt = 0.5
title.ja = 1.0
title_localized.title = 0.8
field_boost が 0 のフィールドは検索対象から外します。
これにより、たとえば title.alt のような別名・synonyms 系フィールドを弱めに扱えます。
title.original を強めると、原題の一致を重視します。title.alt を弱めると、別名・synonyms の影響を抑えます。title_localized.title を上げると、ローカライズタイトルを強く見ます。1.0 から始め、ノイズが出る field を下げるのがおすすめです。デモページでは、全体に対して dis_max を適用するオプションがあります。
dis_max は、複数の検索条件に一致した場合に、最も高いスコアを主に採用するための仕組みです。
通常の bool.should では、複数条件に一致するとスコアが合算されます。
一方、dis_max では最高スコアを中心に評価し、必要に応じて tie_breaker によって他の一致も少しだけ加点できます。
term / prefix / ngram / edge_ngram などに同時に一致した場合、スコアが過剰に積み上がることがあります。
そのような場合に dis_max を使うことで、過剰加点を抑えられます。
公式ドキュメント: dis_max query
OpenSearch の _score は、検索条件に基づくテキストスコアと、補助的なスコアリング関数を組み合わせて算出します。
現在の基本方針は以下です。
final_score = text_query_score + function_score_sum
検索条件ごとのスコアです。
例:
これらは基本的に bool.should で組み合わされます。
複数条件に一致した場合、それぞれのスコアが加算されます。
ただし、dis_max を有効にした場合は、最高スコアを中心に評価されます。
検索結果に対して、人気度や日付による補助スコアを加算します。
利用する代表的な指標は以下です。
num_list_usersnum_favoritespopularitystart_date公式ドキュメント: function_score query
anime / manga におけるリスト登録者数です。
値が大きくなりやすいため、log2p などで圧縮してスコアに反映します。
主に anime / manga のスコアリングに利用します。
character / people / company におけるお気に入り数です。
anime / manga における num_list_users と同様に、人気指標としてスコアリングに利用します。
主に以下のカテゴリで利用します。
カテゴリごとに正規化された人気スコアです。
0〜1の値を取り、1に近いほど人気が高いことを表します。
基準はカテゴリごとに異なります。
popularity はすでに 0〜1 に正規化されているため、基本的には modifier: none で扱います。
anime / manga などの放映日・開始日をもとにしたスコアです。
0〜1の値に正規化して加算します。
start_date は null 許可のため、exists filter を付けたうえで script_score として扱います。
デモページでは、start_date や popularity のスコア関数をグラフで確認できます。
これにより、入力した boost や curve 設定が、どの程度スコアに影響するかを視覚的に確認できます。
Traversal は横断検索で使われるため、カテゴリ間で意味が大きくずれない指標を使うことが重要です。
代表的には popularity を利用します。
Traversal All ではカテゴリをまたぐ msearch を行うため、カテゴリごとに異なるフィールドを強く使いすぎると比較が難しくなる場合があります。
Advanced は単一カテゴリに対する検索なので、カテゴリごとに適した指標を使います。
主な補助スコア:
num_list_userspopularitystart_date主な補助スコア:
num_favoritespopularityTraversal All 検索では、検索結果が特定のカテゴリに偏りすぎないように、カテゴリごとに表示できる件数の上限を決めています。
たとえば最大10件表示する場合、anime / manga / character / people / company からそれぞれ2〜3件ずつ出すように調整されます。
そのため、全体スコア順だけで並べるのではなく、カテゴリごとの候補をバランスよく混ぜた結果になります。
カテゴリごとの表示上限を cap と呼びます。
対象例:
cap:animecap:mangacap:charactercap:peoplecap:companycap を調整することで、Traversal All におけるカテゴリごとの表示件数を制御できます。
Traversal All では、カテゴリごとの重みを調整できます。
対象例:
traversalCategoryWeight:animetraversalCategoryWeight:mangatraversalCategoryWeight:charactertraversalCategoryWeight:peopletraversalCategoryWeight:companyこの値により、カテゴリ代表スコアを調整し、カテゴリの並び順や表示されやすさを検証できます。
C++ や !+! のような記号を含む検索では、analyzer によって token が生成されない場合があります。
例:
en_analyzer → tokens: []
tri_gram_analyzer → tokens: []
raw_analyzer → token: !+!
この場合、通常の match / ngram ではヒットせず、.raw に対する term / prefix でのみヒットする可能性があります。
タイトル全体が !+! と一致
→ term on .raw
タイトルが !+! で始まる
→ prefix on .raw
タイトル途中に !+! を含む
この場合、現状の ngram analyzer が記号を token 化しない場合はヒットしにくくなります。
対応するには、記号や punctuation を保持する ngram field の追加が必要です。
デモページでは、記号検索の切り分け用に以下を表示します。
これにより、+ がスペース化されていないか、\+ のように不要な escape が入っていないかを確認できます。
各検索条件には _name を付け、検索結果に matched_queries として表示できるようにしています。
これにより、検索結果ごとにどの条件が発火したかを確認できます。
例:
termprefixphrasengramedgem_phrasemp_prefixmatchbool_prefixデモページでは、条件別スコアの概算を表示できます。
例:
txt 68.70 · members 23.20 · pop 30.00 · date 23.77
これにより、テキスト一致・人気指標・日付補正のどれが順位に効いているかを確認できます。
matched_queries や条件別スコア表示は、検索品質の検証を補助するための表示です。
特に Traversal All や msearch を利用する場合、本検索と条件別再スコアリングの対象 field が完全に一致しないと、chip 表示と実際のヒット条件がずれることがあります。
検索品質を評価するときは、以下を分けて確認します。
各検索条件に _name を付けることで、検索結果ごとにどの条件が一致したかを確認できます。
確認例:
OpenSearch の _explain を利用すると、上位結果のスコア内訳を確認できます。
特に以下を見ると、調整がしやすくなります。
Traversal All では、検索スコアだけでなくカテゴリごとの cap や weight による表示制御が入ります。
そのため、評価時には以下を分けて見る必要があります。
_scorengram / edge_ngram は便利ですが、候補を広く拾います。
以下を比較しながら調整します。
minimum_should_match を設定するfield_boost でノイズの多い field を弱めるmatched_queries で ngram だけが発火していないか確認する実際の最適値は検索ログや期待結果セットを見ながら調整します。
ただし、初期値としては以下の考え方が参考になります。
term 高
match_phrase 中〜高
match_phrase_prefix 中
phrase_prefix 中
edge_ngram 中〜低
prefix 中〜低
match 中〜低
match_bool_prefix 中〜低
ngram 低
num_list_users log圧縮して利用
num_favorites log圧縮して利用
popularity 0..1 のため modifier none
start_date 0..1 に正規化して weight 調整
match:
長い検索語で候補が少ないときに 75% などを試す
ngram:
部分一致のノイズが多いときに 60%〜75% を試す
edge_ngram:
入力補完候補が広がりすぎるときに 60%〜75% を試す
短い検索語:
基本的に無効
長い検索語:
AUTO を低 boost で検証
fuzziness min length:
5〜6文字程度から開始
本検索ロジックは、以下の方針で構成されています。
最終的な検索品質は、boost 値だけでなく、どの検索条件を採用するか、カテゴリごとの表示制御をどうするか、記号検索をどこまで対応するかによって決まります。
この章は、既存の説明に対する追記です。既存仕様の本文は変更せず、最新版デモページで設定できる項目のうち、本文だけでは分かりにくいものを補足します。
デモページでは、テキスト一致以外の補助スコアを調整するために以下を入力できます。
boost:scoreboost:popuilarityboost:start_dateboost:score は、カテゴリごとの主要な人気指標に対する重みです。
利用される field はカテゴリによって異なります。
num_list_usersnum_favoritesanime / manga では、リスト登録者数を人気指標として扱います。
character / people / company では、お気に入り登録数を人気指標として扱います。
boost:popuilarity は、0〜1に正規化された popularity に対する重みです。
popularity はカテゴリごとの cap によって正規化されます。
boost:start_date は、start_date による日付補正の重みです。
start_date は主に anime / manga の放映日・開始日補正として利用します。
null / missing の場合は加点しません。
デモページには、同じ cap という言葉を使う項目が複数あります。
意味が異なるため、区別して扱います。
popularity cap は、人気指標を 0〜1 に正規化するための閾値です。
入力項目は以下です。
cap:animecap:mangacap:charactercap:peoplecap:companyたとえば cap:character = 10000 の場合、num_favorites が 10,000 件以上の character は popularity = 1 として扱います。
5,000 件であれば popularity = 0.5 のように扱います。
カテゴリごとに元データの分布が異なるため、同じ閾値を使わず、カテゴリ別に調整します。
代表的な考え方は以下です。
num_list_users を基準に正規化num_list_users を基準に正規化num_favorites を基準に正規化num_favorites を基準に正規化num_favorites を基準に正規化Traversal All の cap は、カテゴリごとの表示件数上限です。
こちらは popularity の正規化ではなく、all検索の表示バランスを調整するために使います。
たとえば、Traversal All の表示上限が30件の場合に、anime / manga / character / people / company をどの程度ずつ表示するかを制御します。
popularity cap:
人気スコアを作るための閾値
traversal cap:
all検索でカテゴリごとに何件表示するかの上限
デモページの popularity 関数グラフは、各カテゴリの元指標が popularity に変換される様子を確認するためのものです。
たとえば cap:character = 10000 の場合、グラフでは以下のような変換を確認できます。
num_favorites = 0 → popularity = 0
num_favorites = 5000 → popularity = 0.5
num_favorites = 10000 → popularity = 1
num_favorites > 10000 → popularity = 1
このグラフを見ることで、cap が低すぎて多くのデータが 1 に張り付いていないか、逆に高すぎて人気補正がほとんど効いていないかを確認できます。
デモページの start_date 関数グラフは、放映日・開始日がどの程度スコアに反映されるかを確認するためのものです。
基本的な考え方は以下です。
date_func, date_center_days, date_scale_days を変更すると、日付補正の効き方を比較できます。
デモページでは、以前のプリセットJSONで使っていた一部のキーも読み取れるようにしています。
現在のUI名と旧キーの対応は以下です。
| 旧キー | 現在の扱い |
|---|---|
match_phrase_slop |
slop_match_phrase として扱う |
match_phrase_prefix_slop |
slop_match_phrase_prefix として扱う |
max_expansions |
max_expansions:phrase_prefix / max_expansions:match_phrase_prefix の既定値として扱う |
field_title_original |
field_boost:title.original として扱う |
field_title_en |
field_boost:title.en として扱う |
field_title_alt |
field_boost:title.alt として扱う |
field_title_ja |
field_boost:title.ja として扱う |
field_title_localized |
field_boost:title_localized.title として扱う |
pop_cap_anime |
cap:anime として扱う |
pop_cap_manga |
cap:manga として扱う |
pop_cap_character |
cap:character として扱う |
pop_cap_person |
cap:people として扱う |
pop_cap_company |
cap:company として扱う |
この互換対応により、過去に保存した検証条件をそのまま貼り付けても、現在のUI項目へ可能な範囲で反映できます。
ただし、新旧で意味が変わった項目がある場合は、現在のUI上の値を優先して確認してください。
過去の検証条件には、以下のような項目が含まれていることがあります。
{
"boost_term": "30",
"boost_prefix": "10",
"boost_phrase_prefix": "1",
"boost_ngram": "0",
"boost_edge_ngram": "0",
"boost_match_phrase": "1",
"match_phrase_slop": "0",
"boost_match_phrase_prefix": "1",
"match_phrase_prefix_slop": "0",
"boost_match": "1",
"boost_match_bool_prefix": "0",
"minimum_should_match": "20%",
"max_expansions": "0",
"fuzziness": "",
"field_title_original": "1",
"field_title_en": "1",
"field_title_alt": "1",
"field_title_ja": "1",
"field_title_localized": "1",
"boost_popuilarity": "30",
"boost_start_date": "30",
"date_func": "gauss",
"date_center_days": "0",
"date_scale_days": "365",
"pop_func": "linear",
"pop_cap_anime": "300000",
"pop_cap_manga": "45000",
"pop_cap_character": "10000",
"pop_cap_person": "5000",
"pop_cap_company": "1000"
}
これらの項目は、現在のUIに合わせて読み替えながら利用します。
本文中の cap という表現は、文脈によって以下のどちらかを指します。
READMEを読む際は、この2つを混同しないようにしてください。
また、character / people / company の人気指標は num_favorites を使うため、anime / manga の num_list_users とは値の分布が異なります。
そのため、cap:character, cap:people, cap:company は anime / manga とは別に調整する必要があります。