fields

異なる目的のために同じフィールドを異なる方法でインデックスすることはしばしば有用です。これが multi-fields の目的です。たとえば、string フィールドは、全文検索のために text フィールドとしてマッピングされ、ソートや集計のために keyword フィールドとしてマッピングされる可能性があります。

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "city": {
  6. "type": "text",
  7. "fields": {
  8. "raw": {
  9. "type": "keyword"
  10. }
  11. }
  12. }
  13. }
  14. },
  15. )
  16. print(resp)
  17. resp1 = client.index(
  18. index="my-index-000001",
  19. id="1",
  20. document={
  21. "city": "New York"
  22. },
  23. )
  24. print(resp1)
  25. resp2 = client.index(
  26. index="my-index-000001",
  27. id="2",
  28. document={
  29. "city": "York"
  30. },
  31. )
  32. print(resp2)
  33. resp3 = client.search(
  34. index="my-index-000001",
  35. query={
  36. "match": {
  37. "city": "york"
  38. }
  39. },
  40. sort={
  41. "city.raw": "asc"
  42. },
  43. aggs={
  44. "Cities": {
  45. "terms": {
  46. "field": "city.raw"
  47. }
  48. }
  49. },
  50. )
  51. print(resp3)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. mappings: {
  5. properties: {
  6. city: {
  7. type: 'text',
  8. fields: {
  9. raw: {
  10. type: 'keyword'
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }
  17. )
  18. puts response
  19. response = client.index(
  20. index: 'my-index-000001',
  21. id: 1,
  22. body: {
  23. city: 'New York'
  24. }
  25. )
  26. puts response
  27. response = client.index(
  28. index: 'my-index-000001',
  29. id: 2,
  30. body: {
  31. city: 'York'
  32. }
  33. )
  34. puts response
  35. response = client.search(
  36. index: 'my-index-000001',
  37. body: {
  38. query: {
  39. match: {
  40. city: 'york'
  41. }
  42. },
  43. sort: {
  44. 'city.raw' => 'asc'
  45. },
  46. aggregations: {
  47. "Cities": {
  48. terms: {
  49. field: 'city.raw'
  50. }
  51. }
  52. }
  53. }
  54. )
  55. puts response

Go

  1. {
  2. res, err := es.Indices.Create(
  3. "my-index-000001",
  4. es.Indices.Create.WithBody(strings.NewReader(`{
  5. "mappings": {
  6. "properties": {
  7. "city": {
  8. "type": "text",
  9. "fields": {
  10. "raw": {
  11. "type": "keyword"
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }`)),
  18. )
  19. fmt.Println(res, err)
  20. }
  21. {
  22. res, err := es.Index(
  23. "my-index-000001",
  24. strings.NewReader(`{
  25. "city": "New York"
  26. }`),
  27. es.Index.WithDocumentID("1"),
  28. es.Index.WithPretty(),
  29. )
  30. fmt.Println(res, err)
  31. }
  32. {
  33. res, err := es.Index(
  34. "my-index-000001",
  35. strings.NewReader(`{
  36. "city": "York"
  37. }`),
  38. es.Index.WithDocumentID("2"),
  39. es.Index.WithPretty(),
  40. )
  41. fmt.Println(res, err)
  42. }
  43. {
  44. res, err := es.Search(
  45. es.Search.WithIndex("my-index-000001"),
  46. es.Search.WithBody(strings.NewReader(`{
  47. "query": {
  48. "match": {
  49. "city": "york"
  50. }
  51. },
  52. "sort": {
  53. "city.raw": "asc"
  54. },
  55. "aggs": {
  56. "Cities": {
  57. "terms": {
  58. "field": "city.raw"
  59. }
  60. }
  61. }
  62. }`)),
  63. es.Search.WithPretty(),
  64. )
  65. fmt.Println(res, err)
  66. }

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. city: {
  6. type: "text",
  7. fields: {
  8. raw: {
  9. type: "keyword",
  10. },
  11. },
  12. },
  13. },
  14. },
  15. });
  16. console.log(response);
  17. const response1 = await client.index({
  18. index: "my-index-000001",
  19. id: 1,
  20. document: {
  21. city: "New York",
  22. },
  23. });
  24. console.log(response1);
  25. const response2 = await client.index({
  26. index: "my-index-000001",
  27. id: 2,
  28. document: {
  29. city: "York",
  30. },
  31. });
  32. console.log(response2);
  33. const response3 = await client.search({
  34. index: "my-index-000001",
  35. query: {
  36. match: {
  37. city: "york",
  38. },
  39. },
  40. sort: {
  41. "city.raw": "asc",
  42. },
  43. aggs: {
  44. Cities: {
  45. terms: {
  46. field: "city.raw",
  47. },
  48. },
  49. },
  50. });
  51. console.log(response3);

Console

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "city": {
  6. "type": "text",
  7. "fields": {
  8. "raw": {
  9. "type": "keyword"
  10. }
  11. }
  12. }
  13. }
  14. }
  15. }
  16. PUT my-index-000001/_doc/1
  17. {
  18. "city": "New York"
  19. }
  20. PUT my-index-000001/_doc/2
  21. {
  22. "city": "York"
  23. }
  24. GET my-index-000001/_search
  25. {
  26. "query": {
  27. "match": {
  28. "city": "york"
  29. }
  30. },
  31. "sort": {
  32. "city.raw": "asc"
  33. },
  34. "aggs": {
  35. "Cities": {
  36. "terms": {
  37. "field": "city.raw"
  38. }
  39. }
  40. }
  41. }
city.raw フィールドは keyword バージョンの city フィールドです。
city フィールドは全文検索に使用できます。
city.raw フィールドはソートと集計に使用できます。

既存のフィールドに multi-fields を追加するには、update mapping API を使用できます。

multi-field を追加するときにインデックス(またはデータストリーム)にドキュメントが含まれている場合、それらのドキュメントには新しい multi-field の値がありません。新しい multi-field を update by query API で埋めることができます。

multi-field マッピングは親フィールドのマッピングとは完全に独立しています。multi-field は親フィールドからマッピングオプションを継承しません。multi-fields は元の _source フィールドを変更しません。

Multi-fields with multiple analyzers

multi-fields の別の使用例は、同じフィールドを異なる方法で分析して関連性を高めることです。たとえば、テキストを単語に分割する standard analyzer でフィールドをインデックスし、さらに単語をそのルート形に変換する english analyzer でインデックスすることができます。

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "text": {
  6. "type": "text",
  7. "fields": {
  8. "english": {
  9. "type": "text",
  10. "analyzer": "english"
  11. }
  12. }
  13. }
  14. }
  15. },
  16. )
  17. print(resp)
  18. resp1 = client.index(
  19. index="my-index-000001",
  20. id="1",
  21. document={
  22. "text": "quick brown fox"
  23. },
  24. )
  25. print(resp1)
  26. resp2 = client.index(
  27. index="my-index-000001",
  28. id="2",
  29. document={
  30. "text": "quick brown foxes"
  31. },
  32. )
  33. print(resp2)
  34. resp3 = client.search(
  35. index="my-index-000001",
  36. query={
  37. "multi_match": {
  38. "query": "quick brown foxes",
  39. "fields": [
  40. "text",
  41. "text.english"
  42. ],
  43. "type": "most_fields"
  44. }
  45. },
  46. )
  47. print(resp3)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. mappings: {
  5. properties: {
  6. text: {
  7. type: 'text',
  8. fields: {
  9. english: {
  10. type: 'text',
  11. analyzer: 'english'
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }
  18. )
  19. puts response
  20. response = client.index(
  21. index: 'my-index-000001',
  22. id: 1,
  23. body: {
  24. text: 'quick brown fox'
  25. }
  26. )
  27. puts response
  28. response = client.index(
  29. index: 'my-index-000001',
  30. id: 2,
  31. body: {
  32. text: 'quick brown foxes'
  33. }
  34. )
  35. puts response
  36. response = client.search(
  37. index: 'my-index-000001',
  38. body: {
  39. query: {
  40. multi_match: {
  41. query: 'quick brown foxes',
  42. fields: [
  43. 'text',
  44. 'text.english'
  45. ],
  46. type: 'most_fields'
  47. }
  48. }
  49. }
  50. )
  51. puts response

Go

  1. {
  2. res, err := es.Indices.Create(
  3. "my-index-000001",
  4. es.Indices.Create.WithBody(strings.NewReader(`{
  5. "mappings": {
  6. "properties": {
  7. "text": {
  8. "type": "text",
  9. "fields": {
  10. "english": {
  11. "type": "text",
  12. "analyzer": "english"
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }`)),
  19. )
  20. fmt.Println(res, err)
  21. }
  22. {
  23. res, err := es.Index(
  24. "my-index-000001",
  25. strings.NewReader(`{
  26. "text": "quick brown fox"
  27. } `),
  28. es.Index.WithDocumentID("1"),
  29. es.Index.WithPretty(),
  30. )
  31. fmt.Println(res, err)
  32. }
  33. {
  34. res, err := es.Index(
  35. "my-index-000001",
  36. strings.NewReader(`{
  37. "text": "quick brown foxes"
  38. } `),
  39. es.Index.WithDocumentID("2"),
  40. es.Index.WithPretty(),
  41. )
  42. fmt.Println(res, err)
  43. }
  44. {
  45. res, err := es.Search(
  46. es.Search.WithIndex("my-index-000001"),
  47. es.Search.WithBody(strings.NewReader(`{
  48. "query": {
  49. "multi_match": {
  50. "query": "quick brown foxes",
  51. "fields": [
  52. "text",
  53. "text.english"
  54. ],
  55. "type": "most_fields"
  56. }
  57. }
  58. }`)),
  59. es.Search.WithPretty(),
  60. )
  61. fmt.Println(res, err)
  62. }

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. text: {
  6. type: "text",
  7. fields: {
  8. english: {
  9. type: "text",
  10. analyzer: "english",
  11. },
  12. },
  13. },
  14. },
  15. },
  16. });
  17. console.log(response);
  18. const response1 = await client.index({
  19. index: "my-index-000001",
  20. id: 1,
  21. document: {
  22. text: "quick brown fox",
  23. },
  24. });
  25. console.log(response1);
  26. const response2 = await client.index({
  27. index: "my-index-000001",
  28. id: 2,
  29. document: {
  30. text: "quick brown foxes",
  31. },
  32. });
  33. console.log(response2);
  34. const response3 = await client.search({
  35. index: "my-index-000001",
  36. query: {
  37. multi_match: {
  38. query: "quick brown foxes",
  39. fields: ["text", "text.english"],
  40. type: "most_fields",
  41. },
  42. },
  43. });
  44. console.log(response3);

Console

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "text": {
  6. "type": "text",
  7. "fields": {
  8. "english": {
  9. "type": "text",
  10. "analyzer": "english"
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }
  17. PUT my-index-000001/_doc/1
  18. { "text": "quick brown fox" }
  19. PUT my-index-000001/_doc/2
  20. { "text": "quick brown foxes" }
  21. GET my-index-000001/_search
  22. {
  23. "query": {
  24. "multi_match": {
  25. "query": "quick brown foxes",
  26. "fields": [
  27. "text",
  28. "text.english"
  29. ],
  30. "type": "most_fields"
  31. }
  32. }
  33. }
text フィールドは standard analyzer を使用します。
text.english フィールドは english analyzer を使用します。
fox で1つのドキュメントを、foxes で別のドキュメントをインデックスします。
texttext.english フィールドの両方をクエリし、スコアを組み合わせます。

text フィールドは最初のドキュメントに fox を含み、2番目のドキュメントに foxes を含みます。text.english フィールドは両方のドキュメントに fox を含みます。なぜなら foxesfox にステムされるからです。

クエリ文字列は standard analyzer によって text フィールドのために分析され、english analyzer によって text.english フィールドのために分析されます。ステムされたフィールドは、foxes のクエリが fox のみを含むドキュメントにも一致することを可能にします。これにより、できるだけ多くのドキュメントに一致させることができます。また、非ステムの text フィールドをクエリすることで、foxes に正確に一致するドキュメントの関連性スコアを向上させます。