検索結果のソート

特定のフィールドに対して1つ以上のソートを追加することができます。各ソートは逆にすることも可能です。ソートはフィールドごとに定義され、_scoreを使用してスコアでソートし、_docを使用してインデックス順でソートします。

次のインデックスマッピングを仮定します:

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "post_date": {
  6. "type": "date"
  7. },
  8. "user": {
  9. "type": "keyword"
  10. },
  11. "name": {
  12. "type": "keyword"
  13. },
  14. "age": {
  15. "type": "integer"
  16. }
  17. }
  18. },
  19. )
  20. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. mappings: {
  5. properties: {
  6. post_date: {
  7. type: 'date'
  8. },
  9. user: {
  10. type: 'keyword'
  11. },
  12. name: {
  13. type: 'keyword'
  14. },
  15. age: {
  16. type: 'integer'
  17. }
  18. }
  19. }
  20. }
  21. )
  22. puts response

Go

  1. res, err := es.Indices.Create(
  2. "my-index-000001",
  3. es.Indices.Create.WithBody(strings.NewReader(`{
  4. "mappings": {
  5. "properties": {
  6. "post_date": {
  7. "type": "date"
  8. },
  9. "user": {
  10. "type": "keyword"
  11. },
  12. "name": {
  13. "type": "keyword"
  14. },
  15. "age": {
  16. "type": "integer"
  17. }
  18. }
  19. }
  20. }`)),
  21. )
  22. fmt.Println(res, err)

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. post_date: {
  6. type: "date",
  7. },
  8. user: {
  9. type: "keyword",
  10. },
  11. name: {
  12. type: "keyword",
  13. },
  14. age: {
  15. type: "integer",
  16. },
  17. },
  18. },
  19. });
  20. console.log(response);

Console

  1. PUT /my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "post_date": { "type": "date" },
  6. "user": {
  7. "type": "keyword"
  8. },
  9. "name": {
  10. "type": "keyword"
  11. },
  12. "age": { "type": "integer" }
  13. }
  14. }
  15. }

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. sort=[
  4. {
  5. "post_date": {
  6. "order": "asc",
  7. "format": "strict_date_optional_time_nanos"
  8. }
  9. },
  10. "user",
  11. {
  12. "name": "desc"
  13. },
  14. {
  15. "age": "desc"
  16. },
  17. "_score"
  18. ],
  19. query={
  20. "term": {
  21. "user": "kimchy"
  22. }
  23. },
  24. )
  25. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. body: {
  4. sort: [
  5. {
  6. post_date: {
  7. order: 'asc',
  8. format: 'strict_date_optional_time_nanos'
  9. }
  10. },
  11. 'user',
  12. {
  13. name: 'desc'
  14. },
  15. {
  16. age: 'desc'
  17. },
  18. '_score'
  19. ],
  20. query: {
  21. term: {
  22. user: 'kimchy'
  23. }
  24. }
  25. }
  26. )
  27. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. sort: [
  4. {
  5. post_date: {
  6. order: "asc",
  7. format: "strict_date_optional_time_nanos",
  8. },
  9. },
  10. "user",
  11. {
  12. name: "desc",
  13. },
  14. {
  15. age: "desc",
  16. },
  17. "_score",
  18. ],
  19. query: {
  20. term: {
  21. user: "kimchy",
  22. },
  23. },
  24. });
  25. console.log(response);

Console

  1. GET /my-index-000001/_search
  2. {
  3. "sort" : [
  4. { "post_date" : {"order" : "asc", "format": "strict_date_optional_time_nanos"}},
  5. "user",
  6. { "name" : "desc" },
  7. { "age" : "desc" },
  8. "_score"
  9. ],
  10. "query" : {
  11. "term" : { "user" : "kimchy" }
  12. }
  13. }
  1. ## 値のソート
  2. 検索応答には、各ドキュメントの`````sort`````値が含まれています。`````format`````パラメータを使用して、[`````date`````](/read/elasticsearch-8-15/9dfa1da42eb162ff.md)および[`````date_nanos`````](/read/elasticsearch-8-15/b43d322aa0194e4b.md)フィールドの`````sort`````値の[日付形式](03b5827d4785ee50.md#built-in-date-formats)を指定します。次の検索は、`````strict_date_optional_time_nanos`````形式の`````post_date`````フィールドの`````sort`````値を返します。
  3. #### Python
  4. ``````python
  5. resp = client.search(
  6. index="my-index-000001",
  7. sort=[
  8. {
  9. "post_date": {
  10. "format": "strict_date_optional_time_nanos"
  11. }
  12. }
  13. ],
  14. query={
  15. "term": {
  16. "user": "kimchy"
  17. }
  18. },
  19. )
  20. print(resp)
  21. `

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. body: {
  4. sort: [
  5. {
  6. post_date: {
  7. format: 'strict_date_optional_time_nanos'
  8. }
  9. }
  10. ],
  11. query: {
  12. term: {
  13. user: 'kimchy'
  14. }
  15. }
  16. }
  17. )
  18. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. sort: [
  4. {
  5. post_date: {
  6. format: "strict_date_optional_time_nanos",
  7. },
  8. },
  9. ],
  10. query: {
  11. term: {
  12. user: "kimchy",
  13. },
  14. },
  15. });
  16. console.log(response);

Console

  1. GET /my-index-000001/_search
  2. {
  3. "sort" : [
  4. { "post_date" : {"format": "strict_date_optional_time_nanos"}}
  5. ],
  6. "query" : {
  7. "term" : { "user" : "kimchy" }
  8. }
  9. }

ソート順

  1. | | |
  2. | --- | --- |
  3. | `````asc````` | 昇順でソート |
  4. | `````desc````` | 降順でソート |
  5. `````_score`````でソートする場合、順序は`````desc`````にデフォルト設定され、他の何かでソートする場合は`````asc`````にデフォルト設定されます。
  6. ## ソートモードオプション
  7. Elasticsearchは、配列または複数値フィールドによるソートをサポートしています。`````mode`````オプションは、ドキュメントが属する配列値の選択を制御します。`````mode`````オプションには、次の値を持つことができます:
  8. | | |
  9. | --- | --- |
  10. | `````min````` | 最小値を選択します。 |
  11. | `````max````` | 最大値を選択します。 |
  12. | `````sum````` | すべての値の合計をソート値として使用します。数値ベースの配列フィールドにのみ適用されます。 |
  13. | `````avg````` | すべての値の平均をソート値として使用します。数値ベースの配列フィールドにのみ適用されます。 |
  14. | `````median````` | すべての値の中央値をソート値として使用します。数値ベースの配列フィールドにのみ適用されます。 |
  15. 昇順ソートのデフォルトソートモードは`````min`````です—最小値が選択されます。降順のデフォルトソートモードは`````max`````です—最大値が選択されます。
  16. ### ソートモードの使用例
  17. 以下の例では、フィールド価格がドキュメントごとに複数の価格を持っています。この場合、結果のヒットは、ドキュメントごとの平均価格に基づいて昇順でソートされます。
  18. #### Python
  19. ``````python
  20. resp = client.index(
  21. index="my-index-000001",
  22. id="1",
  23. refresh=True,
  24. document={
  25. "product": "chocolate",
  26. "price": [
  27. 20,
  28. 4
  29. ]
  30. },
  31. )
  32. print(resp)
  33. resp1 = client.search(
  34. query={
  35. "term": {
  36. "product": "chocolate"
  37. }
  38. },
  39. sort=[
  40. {
  41. "price": {
  42. "order": "asc",
  43. "mode": "avg"
  44. }
  45. }
  46. ],
  47. )
  48. print(resp1)
  49. `

Ruby

  1. response = client.index(
  2. index: 'my-index-000001',
  3. id: 1,
  4. refresh: true,
  5. body: {
  6. product: 'chocolate',
  7. price: [
  8. 20,
  9. 4
  10. ]
  11. }
  12. )
  13. puts response
  14. response = client.search(
  15. body: {
  16. query: {
  17. term: {
  18. product: 'chocolate'
  19. }
  20. },
  21. sort: [
  22. {
  23. price: {
  24. order: 'asc',
  25. mode: 'avg'
  26. }
  27. }
  28. ]
  29. }
  30. )
  31. puts response

Go

  1. {
  2. res, err := es.Index(
  3. "my-index-000001",
  4. strings.NewReader(`{
  5. "product": "chocolate",
  6. "price": [
  7. 20,
  8. 4
  9. ]
  10. }`),
  11. es.Index.WithDocumentID("1"),
  12. es.Index.WithRefresh("true"),
  13. es.Index.WithPretty(),
  14. )
  15. fmt.Println(res, err)
  16. }
  17. {
  18. res, err := es.Search(
  19. es.Search.WithBody(strings.NewReader(`{
  20. "query": {
  21. "term": {
  22. "product": "chocolate"
  23. }
  24. },
  25. "sort": [
  26. {
  27. "price": {
  28. "order": "asc",
  29. "mode": "avg"
  30. }
  31. }
  32. ]
  33. }`)),
  34. es.Search.WithPretty(),
  35. )
  36. fmt.Println(res, err)
  37. }

Js

  1. const response = await client.index({
  2. index: "my-index-000001",
  3. id: 1,
  4. refresh: "true",
  5. document: {
  6. product: "chocolate",
  7. price: [20, 4],
  8. },
  9. });
  10. console.log(response);
  11. const response1 = await client.search({
  12. query: {
  13. term: {
  14. product: "chocolate",
  15. },
  16. },
  17. sort: [
  18. {
  19. price: {
  20. order: "asc",
  21. mode: "avg",
  22. },
  23. },
  24. ],
  25. });
  26. console.log(response1);

Console

  1. PUT /my-index-000001/_doc/1?refresh
  2. {
  3. "product": "chocolate",
  4. "price": [20, 4]
  5. }
  6. POST /_search
  7. {
  8. "query" : {
  9. "term" : { "product" : "chocolate" }
  10. },
  11. "sort" : [
  12. {"price" : {"order" : "asc", "mode" : "avg"}}
  13. ]
  14. }

数値フィールドのソート

数値フィールドに対しては、numeric_typeオプションを使用して値を1つの型から別の型にキャストすることも可能です。このオプションは、["double", "long", "date", "date_nanos"]を受け入れ、ソートフィールドが異なるマッピングを持つ複数のデータストリームやインデックスを横断する検索に役立ちます。

たとえば、これらの2つのインデックスを考えてみてください:

Python

  1. resp = client.indices.create(
  2. index="index_double",
  3. mappings={
  4. "properties": {
  5. "field": {
  6. "type": "double"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'index_double',
  3. body: {
  4. mappings: {
  5. properties: {
  6. field: {
  7. type: 'double'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Indices.Create(
  2. "index_double",
  3. es.Indices.Create.WithBody(strings.NewReader(`{
  4. "mappings": {
  5. "properties": {
  6. "field": {
  7. "type": "double"
  8. }
  9. }
  10. }
  11. }`)),
  12. )
  13. fmt.Println(res, err)

Js

  1. const response = await client.indices.create({
  2. index: "index_double",
  3. mappings: {
  4. properties: {
  5. field: {
  6. type: "double",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. PUT /index_double
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field": { "type": "double" }
  6. }
  7. }
  8. }

Python

  1. resp = client.indices.create(
  2. index="index_long",
  3. mappings={
  4. "properties": {
  5. "field": {
  6. "type": "long"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'index_long',
  3. body: {
  4. mappings: {
  5. properties: {
  6. field: {
  7. type: 'long'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Indices.Create(
  2. "index_long",
  3. es.Indices.Create.WithBody(strings.NewReader(`{
  4. "mappings": {
  5. "properties": {
  6. "field": {
  7. "type": "long"
  8. }
  9. }
  10. }
  11. }`)),
  12. )
  13. fmt.Println(res, err)

Js

  1. const response = await client.indices.create({
  2. index: "index_long",
  3. mappings: {
  4. properties: {
  5. field: {
  6. type: "long",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. PUT /index_long
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field": { "type": "long" }
  6. }
  7. }
  8. }
  1. #### Php
  2. ``````php
  3. $params = [
  4. 'index' => 'index_long,index_double',
  5. 'body' => [
  6. 'sort' => [
  7. [
  8. 'field' => [
  9. 'numeric_type' => 'double',
  10. ],
  11. ],
  12. ],
  13. ],
  14. ];
  15. $response = $client->search($params);
  16. `

Python

  1. resp = client.search(
  2. index="index_long,index_double",
  3. sort=[
  4. {
  5. "field": {
  6. "numeric_type": "double"
  7. }
  8. }
  9. ],
  10. )
  11. print(resp)

Ruby

  1. response = client.search(
  2. index: 'index_long,index_double',
  3. body: {
  4. sort: [
  5. {
  6. field: {
  7. numeric_type: 'double'
  8. }
  9. }
  10. ]
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithIndex("index_long,index_double"),
  3. es.Search.WithBody(strings.NewReader(`{
  4. "sort": [
  5. {
  6. "field": {
  7. "numeric_type": "double"
  8. }
  9. }
  10. ]
  11. }`)),
  12. es.Search.WithPretty(),
  13. )
  14. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. index: "index_long,index_double",
  3. sort: [
  4. {
  5. field: {
  6. numeric_type: "double",
  7. },
  8. },
  9. ],
  10. });
  11. console.log(response);

Console

  1. POST /index_long,index_double/_search
  2. {
  3. "sort" : [
  4. {
  5. "field" : {
  6. "numeric_type" : "double"
  7. }
  8. }
  9. ]
  10. }

上記の例では、index_longインデックスの値はダブルにキャストされ、index_doubleインデックスによって生成された値と互換性を持たせます。また、浮動小数点フィールドをlongに変換することも可能ですが、この場合、浮動小数点は引数以下の最大値(負の値の場合は引数以上の最小値)に置き換えられ、数学的整数に等しくなります。

このオプションは、ミリ秒解像度を使用するdateフィールドをナノ秒解像度のdate_nanosフィールドに変換するためにも使用できます。たとえば、これらの2つのインデックスを考えてみてください:

Python

  1. resp = client.indices.create(
  2. index="index_double",
  3. mappings={
  4. "properties": {
  5. "field": {
  6. "type": "date"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'index_double',
  3. body: {
  4. mappings: {
  5. properties: {
  6. field: {
  7. type: 'date'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Indices.Create(
  2. "index_double",
  3. es.Indices.Create.WithBody(strings.NewReader(`{
  4. "mappings": {
  5. "properties": {
  6. "field": {
  7. "type": "date"
  8. }
  9. }
  10. }
  11. }`)),
  12. )
  13. fmt.Println(res, err)

Js

  1. const response = await client.indices.create({
  2. index: "index_double",
  3. mappings: {
  4. properties: {
  5. field: {
  6. type: "date",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. PUT /index_double
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field": { "type": "date" }
  6. }
  7. }
  8. }

Python

  1. resp = client.indices.create(
  2. index="index_long",
  3. mappings={
  4. "properties": {
  5. "field": {
  6. "type": "date_nanos"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'index_long',
  3. body: {
  4. mappings: {
  5. properties: {
  6. field: {
  7. type: 'date_nanos'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Go

  1. res, err := es.Indices.Create(
  2. "index_long",
  3. es.Indices.Create.WithBody(strings.NewReader(`{
  4. "mappings": {
  5. "properties": {
  6. "field": {
  7. "type": "date_nanos"
  8. }
  9. }
  10. }
  11. }`)),
  12. )
  13. fmt.Println(res, err)

Js

  1. const response = await client.indices.create({
  2. index: "index_long",
  3. mappings: {
  4. properties: {
  5. field: {
  6. type: "date_nanos",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. PUT /index_long
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field": { "type": "date_nanos" }
  6. }
  7. }
  8. }

これらのインデックスの値は異なる解像度で保存されているため、これらのフィールドでのソートは常にdatedate_nanos(昇順)でソートします。numeric_type型オプションを使用すると、ソートの単一解像度を設定できます。dateに設定すると、date_nanosはミリ秒解像度に変換され、date_nanosdateフィールドの値をナノ秒解像度に変換します。

Php

  1. $params = [
  2. 'index' => 'index_long,index_double',
  3. 'body' => [
  4. 'sort' => [
  5. [
  6. 'field' => [
  7. 'numeric_type' => 'date_nanos',
  8. ],
  9. ],
  10. ],
  11. ],
  12. ];
  13. $response = $client->search($params);

Python

  1. resp = client.search(
  2. index="index_long,index_double",
  3. sort=[
  4. {
  5. "field": {
  6. "numeric_type": "date_nanos"
  7. }
  8. }
  9. ],
  10. )
  11. print(resp)

Go

  1. res, err := es.Search(
  2. es.Search.WithIndex("index_long,index_double"),
  3. es.Search.WithBody(strings.NewReader(`{
  4. "sort": [
  5. {
  6. "field": {
  7. "numeric_type": "date_nanos"
  8. }
  9. }
  10. ]
  11. }`)),
  12. es.Search.WithPretty(),
  13. )
  14. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. index: "index_long,index_double",
  3. sort: [
  4. {
  5. field: {
  6. numeric_type: "date_nanos",
  7. },
  8. },
  9. ],
  10. });
  11. console.log(response);

Console

  1. POST /index_long,index_double/_search
  2. {
  3. "sort" : [
  4. {
  5. "field" : {
  6. "numeric_type" : "date_nanos"
  7. }
  8. }
  9. ]
  10. }

オーバーフローを避けるため、date_nanosへの変換は1970年以前および2262年以降の日付には適用できません。ナノ秒はロングとして表現されます。

ネストされたオブジェクト内のソート

Elasticsearchは、1つ以上のネストされたオブジェクト内のフィールドによるソートもサポートしています。ネストされたフィールドによるソートサポートには、次のプロパティを持つnestedソートオプションがあります:

  • path
  • どのネストされたオブジェクトでソートするかを定義します。実際のソートフィールドは、このネストされたオブジェクト内の直接フィールドでなければなりません。ネストされたフィールドでソートする場合、このフィールドは必須です。
  • filter
  • ネストされたパス内の内部オブジェクトが一致する必要があるフィルター。一般的なケースは、ネストされたフィルターまたはクエリ内でクエリ/フィルターを繰り返すことです。デフォルトではfilterはアクティブではありません。
  • max_children
  • ソート値を選択する際に、ルートドキュメントごとに考慮する最大子数。デフォルトは無制限です。
  • nested
  • トップレベルのnestedと同じですが、現在のネストされたオブジェクト内の別のネストされたパスに適用されます。

ネストされたフィールドがnestedコンテキストなしでソートに定義されている場合、Elasticsearchはエラーをスローします。

ネストされたソートの例

以下の例では、offernested型のフィールドです。ネストされたpathを指定する必要があります。そうしないと、Elasticsearchはソート値をキャプチャするネストされたレベルを知りません。

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'term' => [
  5. 'product' => 'chocolate',
  6. ],
  7. ],
  8. 'sort' => [
  9. [
  10. 'offer.price' => [
  11. 'mode' => 'avg',
  12. 'order' => 'asc',
  13. 'nested' => [
  14. 'path' => 'offer',
  15. 'filter' => [
  16. 'term' => [
  17. 'offer.color' => 'blue',
  18. ],
  19. ],
  20. ],
  21. ],
  22. ],
  23. ],
  24. ],
  25. ];
  26. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "term": {
  4. "product": "chocolate"
  5. }
  6. },
  7. sort=[
  8. {
  9. "offer.price": {
  10. "mode": "avg",
  11. "order": "asc",
  12. "nested": {
  13. "path": "offer",
  14. "filter": {
  15. "term": {
  16. "offer.color": "blue"
  17. }
  18. }
  19. }
  20. }
  21. }
  22. ],
  23. )
  24. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. term: {
  5. product: 'chocolate'
  6. }
  7. },
  8. sort: [
  9. {
  10. 'offer.price' => {
  11. mode: 'avg',
  12. order: 'asc',
  13. nested: {
  14. path: 'offer',
  15. filter: {
  16. term: {
  17. 'offer.color' => 'blue'
  18. }
  19. }
  20. }
  21. }
  22. }
  23. ]
  24. }
  25. )
  26. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "term": {
  5. "product": "chocolate"
  6. }
  7. },
  8. "sort": [
  9. {
  10. "offer.price": {
  11. "mode": "avg",
  12. "order": "asc",
  13. "nested": {
  14. "path": "offer",
  15. "filter": {
  16. "term": {
  17. "offer.color": "blue"
  18. }
  19. }
  20. }
  21. }
  22. }
  23. ]
  24. }`)),
  25. es.Search.WithPretty(),
  26. )
  27. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. term: {
  4. product: "chocolate",
  5. },
  6. },
  7. sort: [
  8. {
  9. "offer.price": {
  10. mode: "avg",
  11. order: "asc",
  12. nested: {
  13. path: "offer",
  14. filter: {
  15. term: {
  16. "offer.color": "blue",
  17. },
  18. },
  19. },
  20. },
  21. },
  22. ],
  23. });
  24. console.log(response);

Console

  1. POST /_search
  2. {
  3. "query" : {
  4. "term" : { "product" : "chocolate" }
  5. },
  6. "sort" : [
  7. {
  8. "offer.price" : {
  9. "mode" : "avg",
  10. "order" : "asc",
  11. "nested": {
  12. "path": "offer",
  13. "filter": {
  14. "term" : { "offer.color" : "blue" }
  15. }
  16. }
  17. }
  18. }
  19. ]
  20. }

以下の例では、parentおよびchildフィールドはnested型です。nested.pathは各レベルで指定する必要があります。そうしないと、Elasticsearchはソート値をキャプチャするネストされたレベルを知りません。

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'nested' => [
  5. 'path' => 'parent',
  6. 'query' => [
  7. 'bool' => [
  8. 'must' => [
  9. 'range' => [
  10. 'parent.age' => [
  11. 'gte' => 21,
  12. ],
  13. ],
  14. ],
  15. 'filter' => [
  16. 'nested' => [
  17. 'path' => 'parent.child',
  18. 'query' => [
  19. 'match' => [
  20. 'parent.child.name' => 'matt',
  21. ],
  22. ],
  23. ],
  24. ],
  25. ],
  26. ],
  27. ],
  28. ],
  29. 'sort' => [
  30. [
  31. 'parent.child.age' => [
  32. 'mode' => 'min',
  33. 'order' => 'asc',
  34. 'nested' => [
  35. 'path' => 'parent',
  36. 'filter' => [
  37. 'range' => [
  38. 'parent.age' => [
  39. 'gte' => 21,
  40. ],
  41. ],
  42. ],
  43. 'nested' => [
  44. 'path' => 'parent.child',
  45. 'filter' => [
  46. 'match' => [
  47. 'parent.child.name' => 'matt',
  48. ],
  49. ],
  50. ],
  51. ],
  52. ],
  53. ],
  54. ],
  55. ],
  56. ];
  57. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "nested": {
  4. "path": "parent",
  5. "query": {
  6. "bool": {
  7. "must": {
  8. "range": {
  9. "parent.age": {
  10. "gte": 21
  11. }
  12. }
  13. },
  14. "filter": {
  15. "nested": {
  16. "path": "parent.child",
  17. "query": {
  18. "match": {
  19. "parent.child.name": "matt"
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }
  27. },
  28. sort=[
  29. {
  30. "parent.child.age": {
  31. "mode": "min",
  32. "order": "asc",
  33. "nested": {
  34. "path": "parent",
  35. "filter": {
  36. "range": {
  37. "parent.age": {
  38. "gte": 21
  39. }
  40. }
  41. },
  42. "nested": {
  43. "path": "parent.child",
  44. "filter": {
  45. "match": {
  46. "parent.child.name": "matt"
  47. }
  48. }
  49. }
  50. }
  51. }
  52. }
  53. ],
  54. )
  55. print(resp)

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "nested": {
  5. "path": "parent",
  6. "query": {
  7. "bool": {
  8. "must": {
  9. "range": {
  10. "parent.age": {
  11. "gte": 21
  12. }
  13. }
  14. },
  15. "filter": {
  16. "nested": {
  17. "path": "parent.child",
  18. "query": {
  19. "match": {
  20. "parent.child.name": "matt"
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }
  27. }
  28. },
  29. "sort": [
  30. {
  31. "parent.child.age": {
  32. "mode": "min",
  33. "order": "asc",
  34. "nested": {
  35. "path": "parent",
  36. "filter": {
  37. "range": {
  38. "parent.age": {
  39. "gte": 21
  40. }
  41. }
  42. },
  43. "nested": {
  44. "path": "parent.child",
  45. "filter": {
  46. "match": {
  47. "parent.child.name": "matt"
  48. }
  49. }
  50. }
  51. }
  52. }
  53. }
  54. ]
  55. }`)),
  56. es.Search.WithPretty(),
  57. )
  58. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. nested: {
  4. path: "parent",
  5. query: {
  6. bool: {
  7. must: {
  8. range: {
  9. "parent.age": {
  10. gte: 21,
  11. },
  12. },
  13. },
  14. filter: {
  15. nested: {
  16. path: "parent.child",
  17. query: {
  18. match: {
  19. "parent.child.name": "matt",
  20. },
  21. },
  22. },
  23. },
  24. },
  25. },
  26. },
  27. },
  28. sort: [
  29. {
  30. "parent.child.age": {
  31. mode: "min",
  32. order: "asc",
  33. nested: {
  34. path: "parent",
  35. filter: {
  36. range: {
  37. "parent.age": {
  38. gte: 21,
  39. },
  40. },
  41. },
  42. nested: {
  43. path: "parent.child",
  44. filter: {
  45. match: {
  46. "parent.child.name": "matt",
  47. },
  48. },
  49. },
  50. },
  51. },
  52. },
  53. ],
  54. });
  55. console.log(response);

Console

  1. POST /_search
  2. {
  3. "query": {
  4. "nested": {
  5. "path": "parent",
  6. "query": {
  7. "bool": {
  8. "must": {"range": {"parent.age": {"gte": 21}}},
  9. "filter": {
  10. "nested": {
  11. "path": "parent.child",
  12. "query": {"match": {"parent.child.name": "matt"}}
  13. }
  14. }
  15. }
  16. }
  17. }
  18. },
  19. "sort" : [
  20. {
  21. "parent.child.age" : {
  22. "mode" : "min",
  23. "order" : "asc",
  24. "nested": {
  25. "path": "parent",
  26. "filter": {
  27. "range": {"parent.age": {"gte": 21}}
  28. },
  29. "nested": {
  30. "path": "parent.child",
  31. "filter": {
  32. "match": {"parent.child.name": "matt"}
  33. }
  34. }
  35. }
  36. }
  37. }
  38. ]
  39. }

スクリプトによるソートや地理的距離によるソートでもネストされたソートがサポートされています。

欠損値

missingパラメータは、ソートフィールドが欠落しているドキュメントをどのように扱うかを指定します: missing値は_last_first、またはカスタム値(欠落ドキュメントのソート値として使用されます)に設定できます。デフォルトは_lastです。

たとえば:

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "price": {
  5. "missing": "_last"
  6. }
  7. }
  8. ],
  9. query={
  10. "term": {
  11. "product": "chocolate"
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. price: {
  6. missing: '_last'
  7. }
  8. }
  9. ],
  10. query: {
  11. term: {
  12. product: 'chocolate'
  13. }
  14. }
  15. }
  16. )
  17. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "price": {
  6. "missing": "_last"
  7. }
  8. }
  9. ],
  10. "query": {
  11. "term": {
  12. "product": "chocolate"
  13. }
  14. }
  15. }`)),
  16. es.Search.WithPretty(),
  17. )
  18. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. price: {
  5. missing: "_last",
  6. },
  7. },
  8. ],
  9. query: {
  10. term: {
  11. product: "chocolate",
  12. },
  13. },
  14. });
  15. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort" : [
  4. { "price" : {"missing" : "_last"} }
  5. ],
  6. "query" : {
  7. "term" : { "product" : "chocolate" }
  8. }
  9. }

ネストされた内部オブジェクトがnested.filterと一致しない場合、欠損値が使用されます。

マッピングされていないフィールドの無視

デフォルトでは、フィールドに関連付けられたマッピングがない場合、検索リクエストは失敗します。unmapped_typeオプションを使用すると、マッピングがないフィールドを無視し、それらでソートしないことができます。このパラメータの値は、どのソート値を出力するかを決定するために使用されます。以下は、その使用例です:

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "price": {
  5. "unmapped_type": "long"
  6. }
  7. }
  8. ],
  9. query={
  10. "term": {
  11. "product": "chocolate"
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. price: {
  6. unmapped_type: 'long'
  7. }
  8. }
  9. ],
  10. query: {
  11. term: {
  12. product: 'chocolate'
  13. }
  14. }
  15. }
  16. )
  17. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "price": {
  6. "unmapped_type": "long"
  7. }
  8. }
  9. ],
  10. "query": {
  11. "term": {
  12. "product": "chocolate"
  13. }
  14. }
  15. }`)),
  16. es.Search.WithPretty(),
  17. )
  18. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. price: {
  5. unmapped_type: "long",
  6. },
  7. },
  8. ],
  9. query: {
  10. term: {
  11. product: "chocolate",
  12. },
  13. },
  14. });
  15. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort" : [
  4. { "price" : {"unmapped_type" : "long"} }
  5. ],
  6. "query" : {
  7. "term" : { "product" : "chocolate" }
  8. }
  9. }

クエリされるインデックスのいずれかにpriceのマッピングがない場合、Elasticsearchはそれをlong型のマッピングがあるかのように処理し、このインデックス内のすべてのドキュメントがこのフィールドに値を持たないと見なします。

地理的距離によるソート

  1. #### Python
  2. ``````python
  3. resp = client.search(
  4. sort=[
  5. {
  6. "_geo_distance": {
  7. "pin.location": [
  8. -70,
  9. 40
  10. ],
  11. "order": "asc",
  12. "unit": "km",
  13. "mode": "min",
  14. "distance_type": "arc",
  15. "ignore_unmapped": True
  16. }
  17. }
  18. ],
  19. query={
  20. "term": {
  21. "user": "kimchy"
  22. }
  23. },
  24. )
  25. print(resp)
  26. `

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => [
  7. -70,
  8. 40
  9. ],
  10. order: 'asc',
  11. unit: 'km',
  12. mode: 'min',
  13. distance_type: 'arc',
  14. ignore_unmapped: true
  15. }
  16. }
  17. ],
  18. query: {
  19. term: {
  20. user: 'kimchy'
  21. }
  22. }
  23. }
  24. )
  25. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": [
  7. -70,
  8. 40
  9. ],
  10. "order": "asc",
  11. "unit": "km",
  12. "mode": "min",
  13. "distance_type": "arc",
  14. "ignore_unmapped": true
  15. }
  16. }
  17. ],
  18. "query": {
  19. "term": {
  20. "user": "kimchy"
  21. }
  22. }
  23. }`)),
  24. es.Search.WithPretty(),
  25. )
  26. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": [-70, 40],
  6. order: "asc",
  7. unit: "km",
  8. mode: "min",
  9. distance_type: "arc",
  10. ignore_unmapped: true,
  11. },
  12. },
  13. ],
  14. query: {
  15. term: {
  16. user: "kimchy",
  17. },
  18. },
  19. });
  20. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort" : [
  4. {
  5. "_geo_distance" : {
  6. "pin.location" : [-70, 40],
  7. "order" : "asc",
  8. "unit" : "km",
  9. "mode" : "min",
  10. "distance_type" : "arc",
  11. "ignore_unmapped": true
  12. }
  13. }
  14. ],
  15. "query" : {
  16. "term" : { "user" : "kimchy" }
  17. }
  18. }
  • distance_type
  • 距離を計算する方法。arc(デフォルト)またはplane(長距離および極近くでは不正確ですが、より速い)を使用できます。
  • mode
  • フィールドに複数の地理ポイントがある場合の処理方法。デフォルトでは、昇順でソートする際には最短距離が考慮され、降順でソートする際には最長距離が考慮されます。サポートされている値はminmaxmedianavgです。
  • unit
  • ソート値を計算する際に使用する単位。デフォルトはm(メートル)です。
  • ignore_unmapped
  • マッピングされていないフィールドを欠損値として扱うかどうかを示します。trueに設定すると、フィールドソートでunmapped_typeを指定するのと同じです。デフォルトはfalse(マッピングされていないフィールドが検索を失敗させる)です。

地理的距離によるソートは、設定可能な欠損値をサポートしていません: ドキュメントが距離計算に使用されるフィールドの値を持たない場合、距離は常にInfinityと見なされます。

座標を提供する際にサポートされている形式は次のとおりです:

プロパティとしての緯度経度

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "_geo_distance": {
  5. "pin.location": {
  6. "lat": 40,
  7. "lon": -70
  8. },
  9. "order": "asc",
  10. "unit": "km"
  11. }
  12. }
  13. ],
  14. query={
  15. "term": {
  16. "user": "kimchy"
  17. }
  18. },
  19. )
  20. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => {
  7. lat: 40,
  8. lon: -70
  9. },
  10. order: 'asc',
  11. unit: 'km'
  12. }
  13. }
  14. ],
  15. query: {
  16. term: {
  17. user: 'kimchy'
  18. }
  19. }
  20. }
  21. )
  22. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": {
  7. "lat": 40,
  8. "lon": -70
  9. },
  10. "order": "asc",
  11. "unit": "km"
  12. }
  13. }
  14. ],
  15. "query": {
  16. "term": {
  17. "user": "kimchy"
  18. }
  19. }
  20. }`)),
  21. es.Search.WithPretty(),
  22. )
  23. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": {
  6. lat: 40,
  7. lon: -70,
  8. },
  9. order: "asc",
  10. unit: "km",
  11. },
  12. },
  13. ],
  14. query: {
  15. term: {
  16. user: "kimchy",
  17. },
  18. },
  19. });
  20. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort" : [
  4. {
  5. "_geo_distance" : {
  6. "pin.location" : {
  7. "lat" : 40,
  8. "lon" : -70
  9. },
  10. "order" : "asc",
  11. "unit" : "km"
  12. }
  13. }
  14. ],
  15. "query" : {
  16. "term" : { "user" : "kimchy" }
  17. }
  18. }

WKT文字列としての緯度経度

Well-Known Text形式。

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "_geo_distance": {
  5. "pin.location": "POINT (-70 40)",
  6. "order": "asc",
  7. "unit": "km"
  8. }
  9. }
  10. ],
  11. query={
  12. "term": {
  13. "user": "kimchy"
  14. }
  15. },
  16. )
  17. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => 'POINT (-70 40)',
  7. order: 'asc',
  8. unit: 'km'
  9. }
  10. }
  11. ],
  12. query: {
  13. term: {
  14. user: 'kimchy'
  15. }
  16. }
  17. }
  18. )
  19. puts response

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": "POINT (-70 40)",
  6. order: "asc",
  7. unit: "km",
  8. },
  9. },
  10. ],
  11. query: {
  12. term: {
  13. user: "kimchy",
  14. },
  15. },
  16. });
  17. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": "POINT (-70 40)",
  7. "order": "asc",
  8. "unit": "km"
  9. }
  10. }
  11. ],
  12. "query": {
  13. "term": { "user": "kimchy" }
  14. }
  15. }

Geohash

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "_geo_distance": {
  5. "pin.location": "drm3btev3e86",
  6. "order": "asc",
  7. "unit": "km"
  8. }
  9. }
  10. ],
  11. query={
  12. "term": {
  13. "user": "kimchy"
  14. }
  15. },
  16. )
  17. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => 'drm3btev3e86',
  7. order: 'asc',
  8. unit: 'km'
  9. }
  10. }
  11. ],
  12. query: {
  13. term: {
  14. user: 'kimchy'
  15. }
  16. }
  17. }
  18. )
  19. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": "drm3btev3e86",
  7. "order": "asc",
  8. "unit": "km"
  9. }
  10. }
  11. ],
  12. "query": {
  13. "term": {
  14. "user": "kimchy"
  15. }
  16. }
  17. }`)),
  18. es.Search.WithPretty(),
  19. )
  20. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": "drm3btev3e86",
  6. order: "asc",
  7. unit: "km",
  8. },
  9. },
  10. ],
  11. query: {
  12. term: {
  13. user: "kimchy",
  14. },
  15. },
  16. });
  17. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": "drm3btev3e86",
  7. "order": "asc",
  8. "unit": "km"
  9. }
  10. }
  11. ],
  12. "query": {
  13. "term": { "user": "kimchy" }
  14. }
  15. }

配列としての緯度経度

[lon, lat]形式。ここでのlon/latの順序は、GeoJSONに準拠しています。

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "_geo_distance": {
  5. "pin.location": [
  6. -70,
  7. 40
  8. ],
  9. "order": "asc",
  10. "unit": "km"
  11. }
  12. }
  13. ],
  14. query={
  15. "term": {
  16. "user": "kimchy"
  17. }
  18. },
  19. )
  20. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => [
  7. -70,
  8. 40
  9. ],
  10. order: 'asc',
  11. unit: 'km'
  12. }
  13. }
  14. ],
  15. query: {
  16. term: {
  17. user: 'kimchy'
  18. }
  19. }
  20. }
  21. )
  22. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": [
  7. -70,
  8. 40
  9. ],
  10. "order": "asc",
  11. "unit": "km"
  12. }
  13. }
  14. ],
  15. "query": {
  16. "term": {
  17. "user": "kimchy"
  18. }
  19. }
  20. }`)),
  21. es.Search.WithPretty(),
  22. )
  23. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": [-70, 40],
  6. order: "asc",
  7. unit: "km",
  8. },
  9. },
  10. ],
  11. query: {
  12. term: {
  13. user: "kimchy",
  14. },
  15. },
  16. });
  17. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": [ -70, 40 ],
  7. "order": "asc",
  8. "unit": "km"
  9. }
  10. }
  11. ],
  12. "query": {
  13. "term": { "user": "kimchy" }
  14. }
  15. }

複数の参照ポイント

複数の地理ポイントを、任意のgeo_point形式を含む配列として渡すことができます。たとえば

Python

  1. resp = client.search(
  2. sort=[
  3. {
  4. "_geo_distance": {
  5. "pin.location": [
  6. [
  7. -70,
  8. 40
  9. ],
  10. [
  11. -71,
  12. 42
  13. ]
  14. ],
  15. "order": "asc",
  16. "unit": "km"
  17. }
  18. }
  19. ],
  20. query={
  21. "term": {
  22. "user": "kimchy"
  23. }
  24. },
  25. )
  26. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. sort: [
  4. {
  5. _geo_distance: {
  6. 'pin.location' => [
  7. [
  8. -70,
  9. 40
  10. ],
  11. [
  12. -71,
  13. 42
  14. ]
  15. ],
  16. order: 'asc',
  17. unit: 'km'
  18. }
  19. }
  20. ],
  21. query: {
  22. term: {
  23. user: 'kimchy'
  24. }
  25. }
  26. }
  27. )
  28. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": [
  7. [
  8. -70,
  9. 40
  10. ],
  11. [
  12. -71,
  13. 42
  14. ]
  15. ],
  16. "order": "asc",
  17. "unit": "km"
  18. }
  19. }
  20. ],
  21. "query": {
  22. "term": {
  23. "user": "kimchy"
  24. }
  25. }
  26. }`)),
  27. es.Search.WithPretty(),
  28. )
  29. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. sort: [
  3. {
  4. _geo_distance: {
  5. "pin.location": [
  6. [-70, 40],
  7. [-71, 42],
  8. ],
  9. order: "asc",
  10. unit: "km",
  11. },
  12. },
  13. ],
  14. query: {
  15. term: {
  16. user: "kimchy",
  17. },
  18. },
  19. });
  20. console.log(response);

Console

  1. GET /_search
  2. {
  3. "sort": [
  4. {
  5. "_geo_distance": {
  6. "pin.location": [ [ -70, 40 ], [ -71, 42 ] ],
  7. "order": "asc",
  8. "unit": "km"
  9. }
  10. }
  11. ],
  12. "query": {
  13. "term": { "user": "kimchy" }
  14. }
  15. }

など。

ドキュメントの最終的な距離は、min/max/avgmodeを介して定義された)すべてのポイントの距離になります。

スクリプトベースのソート

カスタムスクリプトに基づいてソートを許可します。以下はその例です:

Python

  1. resp = client.search(
  2. query={
  3. "term": {
  4. "user": "kimchy"
  5. }
  6. },
  7. sort={
  8. "_script": {
  9. "type": "number",
  10. "script": {
  11. "lang": "painless",
  12. "source": "doc['field_name'].value * params.factor",
  13. "params": {
  14. "factor": 1.1
  15. }
  16. },
  17. "order": "asc"
  18. }
  19. },
  20. )
  21. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. term: {
  5. user: 'kimchy'
  6. }
  7. },
  8. sort: {
  9. _script: {
  10. type: 'number',
  11. script: {
  12. lang: 'painless',
  13. source: "doc['field_name'].value * params.factor",
  14. params: {
  15. factor: 1.1
  16. }
  17. },
  18. order: 'asc'
  19. }
  20. }
  21. }
  22. )
  23. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "term": {
  5. "user": "kimchy"
  6. }
  7. },
  8. "sort": {
  9. "_script": {
  10. "type": "number",
  11. "script": {
  12. "lang": "painless",
  13. "source": "doc['field_name'].value * params.factor",
  14. "params": {
  15. "factor": 1.1
  16. }
  17. },
  18. "order": "asc"
  19. }
  20. }
  21. }`)),
  22. es.Search.WithPretty(),
  23. )
  24. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. term: {
  4. user: "kimchy",
  5. },
  6. },
  7. sort: {
  8. _script: {
  9. type: "number",
  10. script: {
  11. lang: "painless",
  12. source: "doc['field_name'].value * params.factor",
  13. params: {
  14. factor: 1.1,
  15. },
  16. },
  17. order: "asc",
  18. },
  19. },
  20. });
  21. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "term": { "user": "kimchy" }
  5. },
  6. "sort": {
  7. "_script": {
  8. "type": "number",
  9. "script": {
  10. "lang": "painless",
  11. "source": "doc['field_name'].value * params.factor",
  12. "params": {
  13. "factor": 1.1
  14. }
  15. },
  16. "order": "asc"
  17. }
  18. }
  19. }

スコアの追跡

フィールドでソートする際、スコアは計算されません。track_scoresをtrueに設定すると、スコアは計算され、追跡されます。

Python

  1. resp = client.search(
  2. track_scores=True,
  3. sort=[
  4. {
  5. "post_date": {
  6. "order": "desc"
  7. }
  8. },
  9. {
  10. "name": "desc"
  11. },
  12. {
  13. "age": "desc"
  14. }
  15. ],
  16. query={
  17. "term": {
  18. "user": "kimchy"
  19. }
  20. },
  21. )
  22. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. track_scores: true,
  4. sort: [
  5. {
  6. post_date: {
  7. order: 'desc'
  8. }
  9. },
  10. {
  11. name: 'desc'
  12. },
  13. {
  14. age: 'desc'
  15. }
  16. ],
  17. query: {
  18. term: {
  19. user: 'kimchy'
  20. }
  21. }
  22. }
  23. )
  24. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "track_scores": true,
  4. "sort": [
  5. {
  6. "post_date": {
  7. "order": "desc"
  8. }
  9. },
  10. {
  11. "name": "desc"
  12. },
  13. {
  14. "age": "desc"
  15. }
  16. ],
  17. "query": {
  18. "term": {
  19. "user": "kimchy"
  20. }
  21. }
  22. }`)),
  23. es.Search.WithPretty(),
  24. )
  25. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. track_scores: true,
  3. sort: [
  4. {
  5. post_date: {
  6. order: "desc",
  7. },
  8. },
  9. {
  10. name: "desc",
  11. },
  12. {
  13. age: "desc",
  14. },
  15. ],
  16. query: {
  17. term: {
  18. user: "kimchy",
  19. },
  20. },
  21. });
  22. console.log(response);

Console

  1. GET /_search
  2. {
  3. "track_scores": true,
  4. "sort" : [
  5. { "post_date" : {"order" : "desc"} },
  6. { "name" : "desc" },
  7. { "age" : "desc" }
  8. ],
  9. "query" : {
  10. "term" : { "user" : "kimchy" }
  11. }
  12. }

メモリの考慮事項

ソート時、関連するソートされたフィールド値がメモリにロードされます。これは、シャードごとにそれらを含むのに十分なメモリが必要であることを意味します。文字列ベースの型の場合、ソートされるフィールドは分析/トークン化されていない必要があります。数値型の場合、可能であれば、型を狭い型(shortintegerfloatなど)に明示的に設定することをお勧めします。