7.11. スコアラー

7.11.1. 概要

Groongaにはスコアー関数をカスタマイズするスコアーモジュールがあります。スコアー関数はマッチしたレコードのスコアーを計算します。デフォルトのスコアー関数は出現単語数をスコアーにします。これはTF(term frequency。単語の出現数)と呼ばれている計算方法です。

TFは高速なスコアー関数ですが、次のケースには適していません。

  • 検索クエリーが「the」や「a」のように非常によく出現する単語を含んでいる。

  • 文書中に「They are keyword, keyword, keyword ... and keyword」というように同じキーワードが大量に含まれている。検索エンジンのスパマーはこのテクニックを使うかもしれません。

スコアー関数でこれらのケースを解決できます。例えば、 TF-IDF (term frequency-inverse document frequency。その文書中での単語の出現数を、文書全体での単語の出現数で割ったもの)は最初のケースを解決できます。 Okapi BM25 は2番目のケースを解決できます。しかし、これらはTFより遅いです。

Groongaは scorer_tf_idf としてTF-IDFベースのスコアラーを提供しています。しかし、Okapi BM25ベースのスコアラーはまだ提供していません。

スコアー関数だけでスコアの計算をする必要はありません。スコアー関数は検索クエリーに非常に依存しています。検索クエリーだけでなく、マッチしたレコードのメタデータも使えないか検討しましょう。

たとえば、Googleはスコアーの計算に ページランク を使っています。あなたも、データの種類(たとえば、「メモ」データよりも「タイトル」データの方が重要など)、タグ、位置情報などを使えないか検討してみましょう。

スコアーの計算をスコアー関数だけで考えることはやめましょう。

7.11.2. 使い方

このセクションではスコアラーの使い方について説明します。

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

サンプルスキーマ:

実行例:

table_create Memos TABLE_HASH_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Memos title COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Memos content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY ShortText \
  --default_tokenizer TokenBigram \
  --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms title_index COLUMN_INDEX|WITH_POSITION Memos title
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms content_index COLUMN_INDEX|WITH_POSITION Memos content
# [[0, 1337566253.89858, 0.000355720520019531], true]

サンプルデータ:

実行例:

load --table Memos
[
{
  "_key": "memo1",
  "title": "Groonga is easy",
  "content": "Groonga is very easy full text search engine!"
},
{
  "_key": "memo2",
  "title": "Mroonga is easy",
  "content": "Mroonga is more easier full text search engine!"
},
{
  "_key": "memo3",
  "title": "Rroonga is easy",
  "content": "Ruby is very helpful."
},
{
  "_key": "memo4",
  "title": "Groonga is fast",
  "content": "Groonga! Groonga! Groonga! Groonga is very fast!"
},
{
  "_key": "memo5",
  "title": "PGroonga is fast",
  "content": "PGroonga is very fast!"
},
{
  "_key": "memo6",
  "title": "PGroonga is useful",
  "content": "SQL is easy because many client libraries exist."
},
{
  "_key": "memo7",
  "title": "Mroonga is also useful",
  "content": "MySQL has replication feature. Mroonga can use it."
}
]
# [[0, 1337566253.89858, 0.000355720520019531], 7]

match_columns の中でscore関数を使うことができます。次に構文を示します。

scorer_tf_idf のように、いくつかのスコアー関数には引数はありません。:

SCORE_FUNCTION(COLUMN)

重みを指定することができます。:

SCORE_FUNCTION(COLUMN) * WEIGHT

scorer_tf_at_most のように引数が必要なスコアー関数もあります。:

SCORE_FUNCTION(COLUMN, ARGUMENT1, ARGUMENT2, ...)

重みを指定することができます。:

SCORE_FUNCTION(COLUMN, ARGUMENT1, ARGUMENT2, ...) * WEIGHT

match_columns ではカラムごとに異なるスコア関数を使うことができます。:

SCORE_FUNCTION1(COLUMN1) ||
  SCORE_FUNCTION2(COLUMN2) * WEIGHT ||
  SCORE_FUNCTION3(COLUMN3, ARGUMENT1) ||
  ...

以下は簡単な使用例です。

実行例:

select Memos \
  --match_columns "scorer_tf_idf(content)" \
  --query "Groonga" \
  --output_columns "content, _score" \
  --sortby "-_score"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga! Groonga! Groonga! Groonga is very fast!",
#         2
#       ],
#       [
#         "Groonga is very easy full text search engine!",
#         1
#       ]
#     ]
#   ]
# ]

Groonga! Groonga! Groonga! Groonga is very fast! には Groonga が4つ含まれています。デフォルトのTFベースのスコアラーを使うと、 _score4 です。しかし、実際は _score2 になります。なぜなら、この select コマンドはTF-IDFベースの scorer_tf_idf() スコアラーを使っているからです。

以下は重みを使った例です。

実行例:

select Memos \
  --match_columns "scorer_tf_idf(content) * 10" \
  --query "Groonga" \
  --output_columns "content, _score" \
  --sortby "-_score"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga! Groonga! Groonga! Groonga is very fast!",
#         22
#       ],
#       [
#         "Groonga is very easy full text search engine!",
#         10
#       ]
#     ]
#   ]
# ]

Groonga! Groonga! Groonga! Groonga is very fast!_score22 です。重みを指定していない前の例では _score2 でした。

以下は必ず引数を1つ指定しなければいけないスコアラーを使う例です。 scorer_tf_at_most スコアラーには引数を1つ指定しなければいけません。このスコアラーを使うと、TFのスコアーの最大値を制限することができます。

実行例:

select Memos \
  --match_columns "scorer_tf_at_most(content, 2.0)" \
  --query "Groonga" \
  --output_columns "content, _score" \
  --sortby "-_score"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga! Groonga! Groonga! Groonga is very fast!",
#         2
#       ],
#       [
#         "Groonga is very easy full text search engine!",
#         1
#       ]
#     ]
#   ]
# ]

Groonga! Groonga! Groonga! Groonga is very fast!Groonga を4つ含んでいます。もし、デフォルトのスコアラーである標準のTFベースのスコアラーを使っていた場合、 _score4 になります。しかし、実際の _score2 です。なぜなら、この select コマンドが使っているスコアラーは最大スコアーを 2 に制限しているからです。

以下は複数のスコアラーを使う例です。

実行例:

select Memos \
  --match_columns "scorer_tf_idf(title) || scorer_tf_at_most(content, 2.0)" \
  --query "Groonga" \
  --output_columns "title, content, _score" \
  --sortby "-_score"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "title",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga is fast",
#         "Groonga! Groonga! Groonga! Groonga is very fast!",
#         3
#       ],
#       [
#         "Groonga is easy",
#         "Groonga is very easy full text search engine!",
#         2
#       ]
#     ]
#   ]
# ]

この --match_columnsscorer_tf_idf(title)scorer_tf_at_most(content, 2.0) を使っています。 _score の値はこれら2つの値の合計になります。

同じ --match_columns の中でデフォルトのスコアラーとカスタムスコアラーを使うことができます。単にマッチ対象のカラムを指定するとデフォルトのスコアラーを使います。

実行例:

select Memos \
  --match_columns "title || scorer_tf_at_most(content, 2.0)" \
  --query "Groonga" \
  --output_columns "title, content, _score" \
  --sortby "-_score"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "title",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga is fast",
#         "Groonga! Groonga! Groonga! Groonga is very fast!",
#         3
#       ],
#       [
#         "Groonga is easy",
#         "Groonga is very easy full text search engine!",
#         2
#       ]
#     ]
#   ]
# ]

この --match_columnstitle にはデフォルトのスコアラー(TF)を使い、 content には scorer_tf_at_most を使います。 _score の値はこれらのスコアラーの結果の合計になります。

7.11.3. 組み込みスコアラー

以下は組み込みのスコアラーです。