スパースベクトルフィールドタイプ

sparse_vector フィールドは、特徴と重みをインデックス化できるため、後で sparse_vector を使用してドキュメントをクエリする際に利用できます。このフィールドは、レガシーの text_expansion クエリでも使用できます。

sparse_vector は、ELSER マッピング と一緒に使用すべきフィールドタイプです。

Python

  1. resp = client.indices.create(
  2. index="my-index",
  3. mappings={
  4. "properties": {
  5. "text.tokens": {
  6. "type": "sparse_vector"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index',
  3. body: {
  4. mappings: {
  5. properties: {
  6. 'text.tokens' => {
  7. type: 'sparse_vector'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response

Js

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

コンソール

  1. PUT my-index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "text.tokens": {
  6. "type": "sparse_vector"
  7. }
  8. }
  9. }
  10. }

ELSER を使用したセマンティック検索 を参照して、ELSER を使用して sparse_vector マッピングフィールドにドキュメントを追加する完全な例を確認してください。

マルチバリュースパースベクトル

スパースベクトルの値の配列を渡すとき、同様の名前の特徴の最大値が選択されます。

論文「長文のための学習されたスパース検索の適応」(https://arxiv.org/pdf/2305.18494.pdf) では、これについて詳しく説明しています。要約すると、研究結果は、表現の集約が通常、スコアの集約よりも優れていることを支持しています。

重複する特徴名を持つインスタンスでは、それらを別々に保存するか、ネストされたフィールドを使用する必要があります。

以下は、重複する特徴名を持つドキュメントを渡す例です。この例では、ポジティブな感情とネガティブな感情の2つのカテゴリが存在します。しかし、検索の目的のために、特定の感情ではなく、全体的な影響も求めています。この例では、impact がマルチバリュースパースベクトルとして保存され、重複する名前の最大値のみが保存されます。より具体的には、ここでの最終的な GET クエリは、_score の ~1.2 を返します(これは max(impact.delicious[0], impact.delicious[1]) であり、相対誤差が 0.4% であるため、近似値です)。

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "text": {
  6. "type": "text",
  7. "analyzer": "standard"
  8. },
  9. "impact": {
  10. "type": "sparse_vector"
  11. },
  12. "positive": {
  13. "type": "sparse_vector"
  14. },
  15. "negative": {
  16. "type": "sparse_vector"
  17. }
  18. }
  19. },
  20. )
  21. print(resp)
  22. resp1 = client.index(
  23. index="my-index-000001",
  24. document={
  25. "text": "I had some terribly delicious carrots.",
  26. "impact": [
  27. {
  28. "I": 0.55,
  29. "had": 0.4,
  30. "some": 0.28,
  31. "terribly": 0.01,
  32. "delicious": 1.2,
  33. "carrots": 0.8
  34. },
  35. {
  36. "I": 0.54,
  37. "had": 0.4,
  38. "some": 0.28,
  39. "terribly": 2.01,
  40. "delicious": 0.02,
  41. "carrots": 0.4
  42. }
  43. ],
  44. "positive": {
  45. "I": 0.55,
  46. "had": 0.4,
  47. "some": 0.28,
  48. "terribly": 0.01,
  49. "delicious": 1.2,
  50. "carrots": 0.8
  51. },
  52. "negative": {
  53. "I": 0.54,
  54. "had": 0.4,
  55. "some": 0.28,
  56. "terribly": 2.01,
  57. "delicious": 0.02,
  58. "carrots": 0.4
  59. }
  60. },
  61. )
  62. print(resp1)
  63. resp2 = client.search(
  64. index="my-index-000001",
  65. query={
  66. "term": {
  67. "impact": {
  68. "value": "delicious"
  69. }
  70. }
  71. },
  72. )
  73. print(resp2)

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. text: {
  6. type: "text",
  7. analyzer: "standard",
  8. },
  9. impact: {
  10. type: "sparse_vector",
  11. },
  12. positive: {
  13. type: "sparse_vector",
  14. },
  15. negative: {
  16. type: "sparse_vector",
  17. },
  18. },
  19. },
  20. });
  21. console.log(response);
  22. const response1 = await client.index({
  23. index: "my-index-000001",
  24. document: {
  25. text: "I had some terribly delicious carrots.",
  26. impact: [
  27. {
  28. I: 0.55,
  29. had: 0.4,
  30. some: 0.28,
  31. terribly: 0.01,
  32. delicious: 1.2,
  33. carrots: 0.8,
  34. },
  35. {
  36. I: 0.54,
  37. had: 0.4,
  38. some: 0.28,
  39. terribly: 2.01,
  40. delicious: 0.02,
  41. carrots: 0.4,
  42. },
  43. ],
  44. positive: {
  45. I: 0.55,
  46. had: 0.4,
  47. some: 0.28,
  48. terribly: 0.01,
  49. delicious: 1.2,
  50. carrots: 0.8,
  51. },
  52. negative: {
  53. I: 0.54,
  54. had: 0.4,
  55. some: 0.28,
  56. terribly: 2.01,
  57. delicious: 0.02,
  58. carrots: 0.4,
  59. },
  60. },
  61. });
  62. console.log(response1);
  63. const response2 = await client.search({
  64. index: "my-index-000001",
  65. query: {
  66. term: {
  67. impact: {
  68. value: "delicious",
  69. },
  70. },
  71. },
  72. });
  73. console.log(response2);

コンソール

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "text": {
  6. "type": "text",
  7. "analyzer": "standard"
  8. },
  9. "impact": {
  10. "type": "sparse_vector"
  11. },
  12. "positive": {
  13. "type": "sparse_vector"
  14. },
  15. "negative": {
  16. "type": "sparse_vector"
  17. }
  18. }
  19. }
  20. }
  21. POST my-index-000001/_doc
  22. {
  23. "text": "I had some terribly delicious carrots.",
  24. "impact": [{"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8},
  25. {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4}],
  26. "positive": {"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8},
  27. "negative": {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4}
  28. }
  29. GET my-index-000001/_search
  30. {
  31. "query": {
  32. "term": {
  33. "impact": {
  34. "value": "delicious"
  35. }
  36. }
  37. }
  38. }

sparse_vector フィールドは、作成された Elasticsearch バージョン 8.0 と 8.10 の間に作成されたインデックスには含めることができません。

sparse_vector フィールドは、厳密に正の値のみをサポートします。負の値は拒否されます。

sparse_vector フィールドは、アナライザー、クエリ、ソート、または集約をサポートしていません。これらは、専門的なクエリ内でのみ使用できます。これらのフィールドで使用することを推奨するクエリは、sparse_vector クエリです。また、レガシーの text_expansion クエリ内でも使用できます。

sparse_vector フィールドは、精度のために 9 ビットの有効桁を保持するだけで、これは約 0.4% の相対誤差に相当します。