copy_to

copy_to パラメータを使用すると、複数のフィールドの値をグループフィールドにコピーでき、その後、単一のフィールドとしてクエリできます。

複数のフィールドを頻繁に検索する場合は、copy_to を使用して検索するフィールドを減らすことで、検索速度を向上させることができます。 できるだけ少ないフィールドで検索するを参照してください。

たとえば、first_name および last_name フィールドは、次のように full_name フィールドにコピーできます:

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "first_name": {
  6. "type": "text",
  7. "copy_to": "full_name"
  8. },
  9. "last_name": {
  10. "type": "text",
  11. "copy_to": "full_name"
  12. },
  13. "full_name": {
  14. "type": "text"
  15. }
  16. }
  17. },
  18. )
  19. print(resp)
  20. resp1 = client.index(
  21. index="my-index-000001",
  22. id="1",
  23. document={
  24. "first_name": "John",
  25. "last_name": "Smith"
  26. },
  27. )
  28. print(resp1)
  29. resp2 = client.search(
  30. index="my-index-000001",
  31. query={
  32. "match": {
  33. "full_name": {
  34. "query": "John Smith",
  35. "operator": "and"
  36. }
  37. }
  38. },
  39. )
  40. print(resp2)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. mappings: {
  5. properties: {
  6. first_name: {
  7. type: 'text',
  8. copy_to: 'full_name'
  9. },
  10. last_name: {
  11. type: 'text',
  12. copy_to: 'full_name'
  13. },
  14. full_name: {
  15. type: 'text'
  16. }
  17. }
  18. }
  19. }
  20. )
  21. puts response
  22. response = client.index(
  23. index: 'my-index-000001',
  24. id: 1,
  25. body: {
  26. first_name: 'John',
  27. last_name: 'Smith'
  28. }
  29. )
  30. puts response
  31. response = client.search(
  32. index: 'my-index-000001',
  33. body: {
  34. query: {
  35. match: {
  36. full_name: {
  37. query: 'John Smith',
  38. operator: 'and'
  39. }
  40. }
  41. }
  42. }
  43. )
  44. puts response

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. first_name: {
  6. type: "text",
  7. copy_to: "full_name",
  8. },
  9. last_name: {
  10. type: "text",
  11. copy_to: "full_name",
  12. },
  13. full_name: {
  14. type: "text",
  15. },
  16. },
  17. },
  18. });
  19. console.log(response);
  20. const response1 = await client.index({
  21. index: "my-index-000001",
  22. id: 1,
  23. document: {
  24. first_name: "John",
  25. last_name: "Smith",
  26. },
  27. });
  28. console.log(response1);
  29. const response2 = await client.search({
  30. index: "my-index-000001",
  31. query: {
  32. match: {
  33. full_name: {
  34. query: "John Smith",
  35. operator: "and",
  36. },
  37. },
  38. },
  39. });
  40. console.log(response2);

Console

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "first_name": {
  6. "type": "text",
  7. "copy_to": "full_name"
  8. },
  9. "last_name": {
  10. "type": "text",
  11. "copy_to": "full_name"
  12. },
  13. "full_name": {
  14. "type": "text"
  15. }
  16. }
  17. }
  18. }
  19. PUT my-index-000001/_doc/1
  20. {
  21. "first_name": "John",
  22. "last_name": "Smith"
  23. }
  24. GET my-index-000001/_search
  25. {
  26. "query": {
  27. "match": {
  28. "full_name": {
  29. "query": "John Smith",
  30. "operator": "and"
  31. }
  32. }
  33. }
  34. }
first_name および last_name フィールドの値は、
full_name フィールドにコピーされます。
first_name および last_name フィールドは、それぞれ名と姓のためにクエリできますが、full_name フィールドは名と姓の両方をクエリできます。

いくつかの重要なポイント:

  • コピーされるのはフィールドの値であり、分析プロセスから得られる用語ではありません。
  • 元の _source フィールドは、コピーされた値を表示するために変更されません。
  • 同じ値を複数のフィールドにコピーできますが、"copy_to": [ "field_1", "field_2" ]
  • 中間フィールドを使用して再帰的にコピーすることはできません。次の構成では、field_1 から field_3 へのデータはコピーされません:

Python

  1. resp = client.indices.create(
  2. index="bad_example_index",
  3. mappings={
  4. "properties": {
  5. "field_1": {
  6. "type": "text",
  7. "copy_to": "field_2"
  8. },
  9. "field_2": {
  10. "type": "text",
  11. "copy_to": "field_3"
  12. },
  13. "field_3": {
  14. "type": "text"
  15. }
  16. }
  17. },
  18. )
  19. print(resp)

Js

  1. const response = await client.indices.create({
  2. index: "bad_example_index",
  3. mappings: {
  4. properties: {
  5. field_1: {
  6. type: "text",
  7. copy_to: "field_2",
  8. },
  9. field_2: {
  10. type: "text",
  11. copy_to: "field_3",
  12. },
  13. field_3: {
  14. type: "text",
  15. },
  16. },
  17. },
  18. });
  19. console.log(response);

Console

  1. PUT bad_example_index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field_1": {
  6. "type": "text",
  7. "copy_to": "field_2"
  8. },
  9. "field_2": {
  10. "type": "text",
  11. "copy_to": "field_3"
  12. },
  13. "field_3": {
  14. "type": "text"
  15. }
  16. }
  17. }
  18. }

代わりに、ソースフィールドから複数のフィールドにコピーします:

Python

  1. resp = client.indices.create(
  2. index="good_example_index",
  3. mappings={
  4. "properties": {
  5. "field_1": {
  6. "type": "text",
  7. "copy_to": [
  8. "field_2",
  9. "field_3"
  10. ]
  11. },
  12. "field_2": {
  13. "type": "text"
  14. },
  15. "field_3": {
  16. "type": "text"
  17. }
  18. }
  19. },
  20. )
  21. print(resp)

Js

  1. const response = await client.indices.create({
  2. index: "good_example_index",
  3. mappings: {
  4. properties: {
  5. field_1: {
  6. type: "text",
  7. copy_to: ["field_2", "field_3"],
  8. },
  9. field_2: {
  10. type: "text",
  11. },
  12. field_3: {
  13. type: "text",
  14. },
  15. },
  16. },
  17. });
  18. console.log(response);

Console

  1. PUT good_example_index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "field_1": {
  6. "type": "text",
  7. "copy_to": ["field_2", "field_3"]
  8. },
  9. "field_2": {
  10. "type": "text"
  11. },
  12. "field_3": {
  13. "type": "text"
  14. }
  15. }
  16. }
  17. }

copy_to は、値がオブジェクトの形式を取るフィールドタイプ(例: date_range)ではサポートされていません。

Dynamic mapping

copy_to を動的マッピングで使用する際は、次の点に注意してください:

  • ターゲットフィールドがインデックスマッピングに存在しない場合、通常の 動的マッピング の動作が適用されます。デフォルトでは、dynamictrue に設定されている場合、存在しないターゲットフィールドはインデックスマッピングに動的に追加されます。
  • dynamicfalse に設定されている場合、ターゲットフィールドはインデックスマッピングに追加されず、値はコピーされません。
  • dynamicstrict に設定されている場合、存在しないフィールドへのコピーはエラーになります。
    • ターゲットフィールドがネストされている場合、copy_to フィールドはネストされたフィールドへの完全なパスを指定する必要があります。完全なパスを省略すると、strict_dynamic_mapping_exception になります。"copy_to": ["parent_field.child_field"] を使用してネストされたフィールドを正しくターゲットにします。
      たとえば:

Python

  1. resp = client.indices.create(
  2. index="test_index",
  3. mappings={
  4. "dynamic": "strict",
  5. "properties": {
  6. "description": {
  7. "properties": {
  8. "notes": {
  9. "type": "text",
  10. "copy_to": [
  11. "description.notes_raw"
  12. ],
  13. "analyzer": "standard",
  14. "search_analyzer": "standard"
  15. },
  16. "notes_raw": {
  17. "type": "keyword"
  18. }
  19. }
  20. }
  21. }
  22. },
  23. )
  24. print(resp)

Js

  1. const response = await client.indices.create({
  2. index: "test_index",
  3. mappings: {
  4. dynamic: "strict",
  5. properties: {
  6. description: {
  7. properties: {
  8. notes: {
  9. type: "text",
  10. copy_to: ["description.notes_raw"],
  11. analyzer: "standard",
  12. search_analyzer: "standard",
  13. },
  14. notes_raw: {
  15. type: "keyword",
  16. },
  17. },
  18. },
  19. },
  20. },
  21. });
  22. console.log(response);

Console

  1. PUT /test_index
  2. {
  3. "mappings": {
  4. "dynamic": "strict",
  5. "properties": {
  6. "description": {
  7. "properties": {
  8. "notes": {
  9. "type": "text",
  10. "copy_to": [ "description.notes_raw"],
  11. "analyzer": "standard",
  12. "search_analyzer": "standard"
  13. },
  14. "notes_raw": {
  15. "type": "keyword"
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
notes フィールドは notes_raw フィールドにコピーされます。 notes_raw のみをターゲットにする代わりに description.notes_raw
をターゲットにすると、strict_dynamic_mapping_exception になります。
この例では、notes_raw はマッピングのルートに定義されておらず、description フィールドの下にあります。
完全修飾パスがないと、Elasticsearch は copy_to ターゲットをルートレベルのフィールドとして解釈し、description の下のネストされたフィールドとしては解釈しません。