関数スコアクエリ

function_score は、クエリによって取得されたドキュメントのスコアを変更することを可能にします。これは、スコア関数が計算コストが高く、フィルタリングされたドキュメントのセットでスコアを計算するだけで十分な場合に便利です。

function_score を使用するには、ユーザーはクエリと、クエリによって返される各ドキュメントの新しいスコアを計算する1つ以上の関数を定義する必要があります。

function_score は、このように1つの関数と一緒に使用できます:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "query": {
  5. "match_all": {}
  6. },
  7. "boost": "5",
  8. "random_score": {},
  9. "boost_mode": "multiply"
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. query: {
  6. match_all: {}
  7. },
  8. boost: '5',
  9. random_score: {},
  10. boost_mode: 'multiply'
  11. }
  12. }
  13. }
  14. )
  15. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "function_score": {
  5. "query": {
  6. "match_all": {}
  7. },
  8. "boost": "5",
  9. "random_score": {},
  10. "boost_mode": "multiply"
  11. }
  12. }
  13. }`)),
  14. es.Search.WithPretty(),
  15. )
  16. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. query: {
  5. match_all: {},
  6. },
  7. boost: "5",
  8. random_score: {},
  9. boost_mode: "multiply",
  10. },
  11. },
  12. });
  13. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "query": { "match_all": {} },
  6. "boost": "5",
  7. "random_score": {},
  8. "boost_mode": "multiply"
  9. }
  10. }
  11. }
サポートされている関数のリストについては、関数スコアを参照してください。

さらに、いくつかの関数を組み合わせることができます。この場合、ドキュメントが特定のフィルタリングクエリに一致する場合にのみ関数を適用することを選択できます。

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "query": {
  5. "match_all": {}
  6. },
  7. "boost": "5",
  8. "functions": [
  9. {
  10. "filter": {
  11. "match": {
  12. "test": "bar"
  13. }
  14. },
  15. "random_score": {},
  16. "weight": 23
  17. },
  18. {
  19. "filter": {
  20. "match": {
  21. "test": "cat"
  22. }
  23. },
  24. "weight": 42
  25. }
  26. ],
  27. "max_boost": 42,
  28. "score_mode": "max",
  29. "boost_mode": "multiply",
  30. "min_score": 42
  31. }
  32. },
  33. )
  34. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. query: {
  6. match_all: {}
  7. },
  8. boost: '5',
  9. functions: [
  10. {
  11. filter: {
  12. match: {
  13. test: 'bar'
  14. }
  15. },
  16. random_score: {},
  17. weight: 23
  18. },
  19. {
  20. filter: {
  21. match: {
  22. test: 'cat'
  23. }
  24. },
  25. weight: 42
  26. }
  27. ],
  28. max_boost: 42,
  29. score_mode: 'max',
  30. boost_mode: 'multiply',
  31. min_score: 42
  32. }
  33. }
  34. }
  35. )
  36. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "function_score": {
  5. "query": {
  6. "match_all": {}
  7. },
  8. "boost": "5",
  9. "functions": [
  10. {
  11. "filter": {
  12. "match": {
  13. "test": "bar"
  14. }
  15. },
  16. "random_score": {},
  17. "weight": 23
  18. },
  19. {
  20. "filter": {
  21. "match": {
  22. "test": "cat"
  23. }
  24. },
  25. "weight": 42
  26. }
  27. ],
  28. "max_boost": 42,
  29. "score_mode": "max",
  30. "boost_mode": "multiply",
  31. "min_score": 42
  32. }
  33. }
  34. }`)),
  35. es.Search.WithPretty(),
  36. )
  37. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. query: {
  5. match_all: {},
  6. },
  7. boost: "5",
  8. functions: [
  9. {
  10. filter: {
  11. match: {
  12. test: "bar",
  13. },
  14. },
  15. random_score: {},
  16. weight: 23,
  17. },
  18. {
  19. filter: {
  20. match: {
  21. test: "cat",
  22. },
  23. },
  24. weight: 42,
  25. },
  26. ],
  27. max_boost: 42,
  28. score_mode: "max",
  29. boost_mode: "multiply",
  30. min_score: 42,
  31. },
  32. },
  33. });
  34. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "query": { "match_all": {} },
  6. "boost": "5",
  7. "functions": [
  8. {
  9. "filter": { "match": { "test": "bar" } },
  10. "random_score": {},
  11. "weight": 23
  12. },
  13. {
  14. "filter": { "match": { "test": "cat" } },
  15. "weight": 42
  16. }
  17. ],
  18. "max_boost": 42,
  19. "score_mode": "max",
  20. "boost_mode": "multiply",
  21. "min_score": 42
  22. }
  23. }
  24. }
クエリ全体のブースト。
サポートされている関数のリストについては、関数スコアを参照してください。

各関数のフィルタリングクエリによって生成されたスコアは重要ではありません。

関数にフィルタが指定されていない場合、これは "match_all": {} を指定することと同等です。

最初に、各ドキュメントは定義された関数によってスコア付けされます。パラメータ score_mode は、計算されたスコアがどのように組み合わされるかを指定します:


| | |
| —- | —- |
| multiply | スコアが乗算される(デフォルト) |
| sum | スコアが合計される |
| avg | スコアが平均される |
| first | 一致するフィルタを持つ最初の関数が適用される
|
| max | 最大スコアが使用される |
| min | 最小スコアが使用される |

スコアは異なるスケールである可能性があるため(例えば、減衰関数の場合は0から1の間ですが、field_value_factorの場合は任意)、また、スコアに対する関数の異なる影響が望ましい場合があるため、各関数のスコアはユーザー定義の weight で調整できます。 weight は、functions 配列(上記の例)内の各関数ごとに定義でき、各関数によって計算されたスコアと乗算されます。重みが他の関数宣言なしで指定された場合、weight は単に weight を返す関数として機能します。

score_modeavg に設定されている場合、個々のスコアは 加重 平均によって組み合わされます。たとえば、2つの関数がスコア1と2を返し、それぞれの重みが3と4の場合、スコアは (1*3+2*4)/(3+4) として組み合わされ、ではなく (1*3+2*4)/2 となります。

新しいスコアは、max_boost パラメータを設定することによって、特定の制限を超えないように制限できます。max_boost のデフォルトは FLT_MAX です。

新しく計算されたスコアは、クエリのスコアと組み合わされます。パラメータ boost_mode は、どのように組み合わされるかを定義します:


| | |
| —- | —- |
| multiply | クエリスコアと関数スコアが乗算される(デフォルト) |
| replace | 関数スコアのみが使用され、クエリスコアは無視される |
| sum | クエリスコアと関数スコアが加算される |
| avg | 平均 |
| max | クエリスコアと関数スコアの最大値 |
| min | クエリスコアと関数スコアの最小値 |

デフォルトでは、スコアを変更しても、どのドキュメントが一致するかは変わりません。特定のスコア閾値を満たさないドキュメントを除外するには、min_score パラメータを希望するスコア閾値に設定できます。

min_score が機能するためには、クエリによって返される すべての ドキュメントにスコアを付け、その後1つずつフィルタリングする必要があります。

function_score クエリは、いくつかのタイプのスコア関数を提供します。

スクリプトスコア

script_score 関数は、別のクエリをラップし、スクリプト式を使用してドキュメント内の他の数値フィールド値から派生した計算でスコアをカスタマイズすることを可能にします。以下は簡単なサンプルです:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "query": {
  5. "match": {
  6. "message": "elasticsearch"
  7. }
  8. },
  9. "script_score": {
  10. "script": {
  11. "source": "Math.log(2 + doc['my-int'].value)"
  12. }
  13. }
  14. }
  15. },
  16. )
  17. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. query: {
  6. match: {
  7. message: 'elasticsearch'
  8. }
  9. },
  10. script_score: {
  11. script: {
  12. source: "Math.log(2 + doc['my-int'].value)"
  13. }
  14. }
  15. }
  16. }
  17. }
  18. )
  19. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. query: {
  5. match: {
  6. message: "elasticsearch",
  7. },
  8. },
  9. script_score: {
  10. script: {
  11. source: "Math.log(2 + doc['my-int'].value)",
  12. },
  13. },
  14. },
  15. },
  16. });
  17. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "query": {
  6. "match": { "message": "elasticsearch" }
  7. },
  8. "script_score": {
  9. "script": {
  10. "source": "Math.log(2 + doc['my-int'].value)"
  11. }
  12. }
  13. }
  14. }
  15. }

Elasticsearch では、すべてのドキュメントスコアは正の 32 ビット浮動小数点数です。

script_score 関数がより高い精度のスコアを生成する場合、それは最も近い 32 ビット浮動小数点数に変換されます。

同様に、スコアは非負でなければなりません。そうでない場合、Elasticsearch はエラーを返します。

異なるスクリプトフィールド値や式に加えて、_score スクリプトパラメータを使用して、ラップされたクエリに基づいてスコアを取得できます。

スクリプトのコンパイルは、より高速な実行のためにキャッシュされます。スクリプトが考慮する必要があるパラメータがある場合は、同じスクリプトを再利用し、パラメータを提供することが望ましいです:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "query": {
  5. "match": {
  6. "message": "elasticsearch"
  7. }
  8. },
  9. "script_score": {
  10. "script": {
  11. "params": {
  12. "a": 5,
  13. "b": 1.2
  14. },
  15. "source": "params.a / Math.pow(params.b, doc['my-int'].value)"
  16. }
  17. }
  18. }
  19. },
  20. )
  21. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. query: {
  6. match: {
  7. message: 'elasticsearch'
  8. }
  9. },
  10. script_score: {
  11. script: {
  12. params: {
  13. a: 5,
  14. b: 1.2
  15. },
  16. source: "params.a / Math.pow(params.b, doc['my-int'].value)"
  17. }
  18. }
  19. }
  20. }
  21. }
  22. )
  23. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. query: {
  5. match: {
  6. message: "elasticsearch",
  7. },
  8. },
  9. script_score: {
  10. script: {
  11. params: {
  12. a: 5,
  13. b: 1.2,
  14. },
  15. source: "params.a / Math.pow(params.b, doc['my-int'].value)",
  16. },
  17. },
  18. },
  19. },
  20. });
  21. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "query": {
  6. "match": { "message": "elasticsearch" }
  7. },
  8. "script_score": {
  9. "script": {
  10. "params": {
  11. "a": 5,
  12. "b": 1.2
  13. },
  14. "source": "params.a / Math.pow(params.b, doc['my-int'].value)"
  15. }
  16. }
  17. }
  18. }
  19. }

注意してください。custom_score クエリとは異なり、クエリのスコアはスクリプトスコアの結果と乗算されます。これを抑制したい場合は、"boost_mode": "replace" を設定してください。

重み

weight スコアは、提供された weight でスコアを乗算することを可能にします。これは、特定のクエリに設定されたブースト値が正規化される一方で、このスコア関数ではそうでないため、時には望ましい場合があります。数値は浮動小数点型です。

Js

  1. "weight" : number

ランダム

random_score は、0 から 1 未満まで均等に分布したスコアを生成します。デフォルトでは、内部の Lucene ドキュメント ID をランダム性のソースとして使用します。これは非常に効率的ですが、残念ながら再現性がありません。なぜなら、ドキュメントはマージによって再番号付けされる可能性があるからです。

スコアを再現可能にしたい場合は、seedfield を提供することができます。最終的なスコアは、このシード、考慮されるドキュメントの field の最小値、およびインデックス名とシャード ID に基づいて計算される塩を基に計算されます。これにより、同じ値を持つが異なるインデックスに保存されているドキュメントは異なるスコアを取得します。同じシャード内にあり、field の値が同じドキュメントは同じスコアを取得しますが、通常はすべてのドキュメントに対して一意の値を持つフィールドを使用することが望ましいです。良いデフォルトの選択肢は、_seq_no フィールドを使用することです。このフィールドの唯一の欠点は、ドキュメントが更新されるとスコアが変わることです。なぜなら、更新操作も _seq_no フィールドの値を更新するからです。

フィールドを設定せずにシードを設定することは可能でしたが、これは _id フィールドのフィールドデータを読み込む必要があるため、メモリを大量に消費するため、非推奨となりました。

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "random_score": {
  5. "seed": 10,
  6. "field": "_seq_no"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. random_score: {
  6. seed: 10,
  7. field: '_seq_no'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "function_score": {
  5. "random_score": {
  6. "seed": 10,
  7. "field": "_seq_no"
  8. }
  9. }
  10. }
  11. }`)),
  12. es.Search.WithPretty(),
  13. )
  14. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. random_score: {
  5. seed: 10,
  6. field: "_seq_no",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "random_score": {
  6. "seed": 10,
  7. "field": "_seq_no"
  8. }
  9. }
  10. }
  11. }

フィールド値ファクター

field_value_factor 関数は、ドキュメントのフィールドを使用してスコアに影響を与えることを可能にします。これは script_score 関数を使用するのに似ていますが、スクリプトのオーバーヘッドを回避します。マルチバリューフィールドで使用される場合、計算にはフィールドの最初の値のみが使用されます。

たとえば、数値 my-int フィールドでインデックスされたドキュメントがあり、このフィールドでドキュメントのスコアに影響を与えたい場合、次のようになります:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "field_value_factor": {
  5. "field": "my-int",
  6. "factor": 1.2,
  7. "modifier": "sqrt",
  8. "missing": 1
  9. }
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. field_value_factor: {
  6. field: 'my-int',
  7. factor: 1.2,
  8. modifier: 'sqrt',
  9. missing: 1
  10. }
  11. }
  12. }
  13. }
  14. )
  15. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. field_value_factor: {
  5. field: "my-int",
  6. factor: 1.2,
  7. modifier: "sqrt",
  8. missing: 1,
  9. },
  10. },
  11. },
  12. });
  13. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "field_value_factor": {
  6. "field": "my-int",
  7. "factor": 1.2,
  8. "modifier": "sqrt",
  9. "missing": 1
  10. }
  11. }
  12. }
  13. }

スコアリングのための次の数式に変換されます:

sqrt(1.2 * doc['my-int'].value)

field_value_factor 関数にはいくつかのオプションがあります:

field ドキュメントから抽出されるフィールド。
factor フィールド値に乗算するオプションのファクター、デフォルトは 1
modifier フィールド値に適用する修飾子、次のいずれかである可能性があります: none, log,
log1p, log2p, ln, ln1p, ln2p, square, sqrt, または reciprocal
デフォルトは none
修飾子 意味
none フィールド値に対して乗算を適用しない
log フィールド値の常用対数を取る。
この関数は負の値を返し、0 と 1 の間の値で使用するとエラーを引き起こすため、log1p を使用することをお勧めします。
log1p フィールド値に 1 を加え、常用対数を取る
log2p フィールド値に 2 を加え、常用対数を取る
ln フィールド値のnatural logarithmを取る。
この関数は負の値を返し、0 と 1 の間の値で使用するとエラーを引き起こすため、ln1p を使用することをお勧めします。
ln1p フィールド値に 1 を加え、自然対数を取る
ln2p フィールド値に 2 を加え、自然対数を取る
square フィールド値を二乗する(自分自身で乗算する)
sqrt フィールド値の平方根を取る
reciprocal フィールド値を逆数にする。1/x では、x がフィールドの値です。
  • missing
  • ドキュメントにそのフィールドがない場合に使用される値。修飾子とファクターは、ドキュメントから読み取られたかのように適用されます。

field_value_score 関数によって生成されたスコアは非負でなければならず、そうでない場合はエラーが発生します。log および ln 修飾子は、0 と 1 の間の値で使用すると負の値を生成します。これを避けるために、フィールドの値を範囲フィルターで制限するか、log1p および ln1p を使用してください。

log() の 0 を取ることや、負の数の平方根を取ることは不正な操作であり、例外が発生します。これを避けるために、フィールドの値を範囲フィルターで制限するか、log1p および ln1p を使用してください。

減衰関数

減衰関数は、ユーザーが指定した原点からのドキュメントの数値フィールド値の距離に応じて減衰する関数でドキュメントにスコアを付けます。これは範囲クエリに似ていますが、ボックスの代わりに滑らかなエッジを持っています。

数値フィールドを持つクエリで距離スコアリングを使用するには、ユーザーは各フィールドに対して originscale を定義する必要があります。origin は、距離が計算される「中心点」を定義するために必要で、scale は減衰率を定義するために必要です。減衰関数は次のように指定されます

Js

  1. "DECAY_FUNCTION": {
  2. "FIELD_NAME": {
  3. "origin": "11, 12",
  4. "scale": "2km",
  5. "offset": "0km",
  6. "decay": 0.33
  7. }
  8. }
DECAY_FUNCTIONlinearexp、または gauss のいずれかである必要があります。
指定されたフィールドは数値、日付、またはジオポイントフィールドでなければなりません。

上記の例では、フィールドは geo_point であり、原点はジオ形式で提供できます。この場合、scaleoffset は単位を指定する必要があります。フィールドが日付フィールドの場合、scaleoffset を日、週などとして設定できます。例:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "gauss": {
  5. "@timestamp": {
  6. "origin": "2013-09-17",
  7. "scale": "10d",
  8. "offset": "5d",
  9. "decay": 0.5
  10. }
  11. }
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. gauss: {
  6. "@timestamp": {
  7. origin: '2013-09-17',
  8. scale: '10d',
  9. offset: '5d',
  10. decay: 0.5
  11. }
  12. }
  13. }
  14. }
  15. }
  16. )
  17. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. gauss: {
  5. "@timestamp": {
  6. origin: "2013-09-17",
  7. scale: "10d",
  8. offset: "5d",
  9. decay: 0.5,
  10. },
  11. },
  12. },
  13. },
  14. });
  15. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "gauss": {
  6. "@timestamp": {
  7. "origin": "2013-09-17",
  8. "scale": "10d",
  9. "offset": "5d",
  10. "decay": 0.5
  11. }
  12. }
  13. }
  14. }
  15. }
原点の日付形式は、マッピングで定義された format に依存します。原点を定義しない場合、現在の時間が使用されます。
offset および decay パラメータはオプションです。
origin 距離を計算するために使用される原点。数値フィールドの場合は数値、日付フィールドの場合は日付、ジオフィールドの場合はジオポイントとして指定する必要があります。
ジオおよび数値フィールドには必須です。日付フィールドの場合、デフォルトは now です。原点に対して日付の数学(たとえば now-1h)がサポートされています。
scale すべてのタイプに必須。計算されたスコアが decay パラメータに等しくなる原点 + オフセットからの距離を定義します。ジオフィールドの場合:数値 + 単位(1km、12m、…)として定義できます。デフォルトの単位はメートルです。日付フィールドの場合:数値 + 単位(”1h”、”10d”、…)として定義できます。デフォルトの単位はミリ秒です。数値フィールド:任意の数値。
offset offset が定義されている場合、減衰関数は定義された offset よりも距離が大きいドキュメントに対してのみ計算されます。デフォルトは 0 です。
decay decay パラメータは、scale で指定された距離でドキュメントがどのようにスコア付けされるかを定義します。decay が定義されていない場合、scale の距離にあるドキュメントは 0.5 のスコアが付けられます。

最初の例では、ドキュメントはホテルを表し、ジオロケーションフィールドを含む可能性があります。指定された場所からホテルがどれだけ遠いかに応じて減衰関数を計算したい場合があります。ガウス関数のスケールを選択するのはすぐにはわからないかもしれませんが、次のように言うことができます。「指定された場所から2kmの距離では、スコアは3分の1に減少する必要があります。」パラメータ「スケール」は、スコア関数が指定された場所から2km離れたホテルに対して0.33のスコアを計算することを保証するために自動的に調整されます。

2番目の例では、フィールド値が2013-09-12から2013-09-22の間のドキュメントは1.0の重みを持ち、その日から15日離れたドキュメントは0.5の重みを持ちます。

サポートされている減衰関数

DECAY_FUNCTION は減衰の形状を決定します:

  • gauss
  • 正常な減衰、計算式:
    Gaussian
    ここで sigma は、スコアが decay の値を取ることを保証するように計算されます。scaleorigin から offset を引いた距離です。
    sigma calc
    正常な減衰、キーワード gauss のグラフを参照して、gauss 関数によって生成された曲線を示します。
  • exp
  • 指数減衰、計算式:
    Exponential
    ここでも、パラメータ lambda は、スコアが decay の値を取ることを保証するように計算されます。scaleorigin から offset を引いた距離です。
    lambda calc
    指数減衰、キーワード exp のグラフを参照して、exp 関数によって生成された曲線を示します。
  • linear
  • 線形減衰、計算式:
    Linear
    ここでも、パラメータ s は、スコアが decay の値を取ることを保証するように計算されます。scaleorigin から offset を引いた距離です。
    s calc
    通常の減衰および指数減衰とは異なり、この関数はフィールド値がユーザーが指定したスケール値の2倍を超えるとスコアを0に設定します。

単一の関数の場合、3つの減衰関数とそのパラメータは次のように視覚化できます(この例ではフィールドは「年齢」と呼ばれます):

decay 2d

マルチバリューフィールド

減衰計算に使用されるフィールドが複数の値を持つ場合、デフォルトでは原点に最も近い値が距離を決定するために選択されます。これは multi_value_mode を設定することで変更できます。

min 距離は最小距離です
max 距離は最大距離です
avg 距離は平均距離です
sum 距離はすべての距離の合計です

例:

Js

  1. "DECAY_FUNCTION": {
  2. "FIELD_NAME": {
  3. "origin": ...,
  4. "scale": ...
  5. },
  6. "multi_value_mode": "avg"
  7. }

詳細な例

特定の町でホテルを探しているとします。予算は限られています。また、ホテルは町の中心に近いことを望んでいるので、ホテルが指定された場所から遠いほど、チェックインする可能性が低くなります。

あなたは、あなたの基準(例えば、「ホテル、ナンシー、禁煙」)に一致するクエリ結果が町の中心までの距離と価格に基づいてスコア付けされることを望んでいます。

直感的には、町の中心を原点として定義し、ホテルから町の中心まで2km歩くことを望んでいるかもしれません。

この場合、ロケーションフィールドの 原点 は町の中心で、スケール は約2kmです。

予算が少ない場合、安いものを高いものよりも好むでしょう。価格フィールドの 原点 は0ユーロで、スケール は支払う意欲がある金額、例えば20ユーロに依存します。

この例では、フィールドは「価格」と呼ばれ、ホテルの価格のためのものであり、「ロケーション」はこのホテルの座標のためのものです。

この場合の price の関数は

Js

  1. "gauss": {
  2. "price": {
  3. "origin": "0",
  4. "scale": "20"
  5. }
  6. }
この減衰関数は linear または exp でも構いません。

location のために:

Js

  1. "gauss": {
  2. "location": {
  3. "origin": "11, 12",
  4. "scale": "2km"
  5. }
  6. }
この減衰関数は linear または exp でも構いません。

これら2つの関数を元のスコアに乗算したい場合、リクエストは次のようになります:

Python

  1. resp = client.search(
  2. query={
  3. "function_score": {
  4. "functions": [
  5. {
  6. "gauss": {
  7. "price": {
  8. "origin": "0",
  9. "scale": "20"
  10. }
  11. }
  12. },
  13. {
  14. "gauss": {
  15. "location": {
  16. "origin": "11, 12",
  17. "scale": "2km"
  18. }
  19. }
  20. }
  21. ],
  22. "query": {
  23. "match": {
  24. "properties": "balcony"
  25. }
  26. },
  27. "score_mode": "multiply"
  28. }
  29. },
  30. )
  31. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. function_score: {
  5. functions: [
  6. {
  7. gauss: {
  8. price: {
  9. origin: '0',
  10. scale: '20'
  11. }
  12. }
  13. },
  14. {
  15. gauss: {
  16. location: {
  17. origin: '11, 12',
  18. scale: '2km'
  19. }
  20. }
  21. }
  22. ],
  23. query: {
  24. match: {
  25. properties: 'balcony'
  26. }
  27. },
  28. score_mode: 'multiply'
  29. }
  30. }
  31. }
  32. )
  33. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "function_score": {
  5. "functions": [
  6. {
  7. "gauss": {
  8. "price": {
  9. "origin": "0",
  10. "scale": "20"
  11. }
  12. }
  13. },
  14. {
  15. "gauss": {
  16. "location": {
  17. "origin": "11, 12",
  18. "scale": "2km"
  19. }
  20. }
  21. }
  22. ],
  23. "query": {
  24. "match": {
  25. "properties": "balcony"
  26. }
  27. },
  28. "score_mode": "multiply"
  29. }
  30. }
  31. }`)),
  32. es.Search.WithPretty(),
  33. )
  34. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. function_score: {
  4. functions: [
  5. {
  6. gauss: {
  7. price: {
  8. origin: "0",
  9. scale: "20",
  10. },
  11. },
  12. },
  13. {
  14. gauss: {
  15. location: {
  16. origin: "11, 12",
  17. scale: "2km",
  18. },
  19. },
  20. },
  21. ],
  22. query: {
  23. match: {
  24. properties: "balcony",
  25. },
  26. },
  27. score_mode: "multiply",
  28. },
  29. },
  30. });
  31. console.log(response);

コンソール

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "functions": [
  6. {
  7. "gauss": {
  8. "price": {
  9. "origin": "0",
  10. "scale": "20"
  11. }
  12. }
  13. },
  14. {
  15. "gauss": {
  16. "location": {
  17. "origin": "11, 12",
  18. "scale": "2km"
  19. }
  20. }
  21. }
  22. ],
  23. "query": {
  24. "match": {
  25. "properties": "balcony"
  26. }
  27. },
  28. "score_mode": "multiply"
  29. }
  30. }
  31. }

次に、3つの可能な減衰関数のそれぞれに対して計算されたスコアがどのように見えるかを示します。

正常な減衰、キーワード gauss

gauss を減衰関数として選択した場合、上記の例の乗数の輪郭と表面プロットは次のようになります:

cd0e18a6 e898 11e2 9b3c f0145078bd6f

ec43c928 e898 11e2 8e0d f3c4519dbd89

元の検索結果が3つのホテルに一致すると仮定します:

  • 「バックパックナップ」
  • 「飲酒運転」
  • 「BnBベルビュー」。

「飲酒運転」は、定義された場所からかなり遠く(ほぼ2km)にあり、あまり安くない(約13ユーロ)ため、低いファクター0.56を得ます。「BnBベルビュー」と「バックパックナップ」は、定義された場所にかなり近いですが、「BnBベルビュー」は安いため、0.86の乗数を得るのに対し、「バックパックナップ」は0.66の値を得ます。

指数減衰、キーワード exp

exp を減衰関数として選択した場合、上記の例の乗数の輪郭と表面プロットは次のようになります:

082975c0 e899 11e2 86f7 174c3a729d64

0b606884 e899 11e2 907b aefc77eefef6

線形減衰、キーワード linear

linear を減衰関数として選択した場合、上記の例の乗数の輪郭と表面プロットは次のようになります:

1775b0ca e899 11e2 9f4a 776b406305c6

19d8b1aa e899 11e2 91bc 6b0553e8d722

減衰関数のサポートされているフィールド

数値、日付、およびジオポイントフィールドのみがサポートされています。

フィールドが欠落している場合は?

数値フィールドがドキュメントに欠落している場合、関数は1を返します。