全文検索

全文検索とは、テキストデータセットの中から特定の用語やフレーズを含むドキュメントを検索し、関連性に基づいて結果をランク付けする機能です。この機能により、正確な用語を見逃してしまう可能性のあるセマンティック検索の限界を克服し、最も正確で文脈に即した検索結果を得ることができます。 さらに、生のテキスト入力を受け付け、手動でベクトル埋め込みを生成する必要なく、テキストデータを自動的にスパース埋め込みに変換することで、ベクトル検索を簡素化します。

関連性スコアリングにBM25アルゴリズムを採用しているこの機能は、特定の検索用語と密接に一致するドキュメントを優先する「検索強化生成(RAG)」のシナリオにおいて、特に有用です。

全文検索とセマンティックベースの密ベクトル検索を統合することで、検索結果の精度と関連性を高めることができます。詳細については、「ハイブリッド検索」を参照してください。

BM25の実装

Milvusは、情報検索システムで広く採用されている関連性評価関数であるBM25アルゴリズムを活用した全文検索機能を提供しており、これを検索ワークフローに統合することで、正確で関連性の高いテキスト検索結果を提供します。

Milvusにおける全文検索は、以下のワークフローに従います:

  1. 生テキストの入力:テキスト文書を挿入するか、プレーンテキストを使用してクエリを指定します。埋め込みモデルは不要です。

  2. テキスト分析:Milvusはアナライザーを使用して、テキストをインデックス化および検索可能な意味のある用語に処理します。

  3. BM25関数による処理:組み込み関数が、これらの用語をBM25スコアリングに最適化されたスパースベクトル表現に変換します。

  4. コレクションへの保存:Milvusは、高速な検索とランキングを実現するために、結果として得られた疎な埋め込みベクトルをコレクションに保存します。

  5. BM25 関連性スコアリング:検索時、Milvus は BM25 スコアリング関数を適用して文書の関連性を計算し、クエリ用語に最も一致する結果をランク付けして返します。

Full Text Search 全文検索

全文検索を使用するには、以下の主な手順に従ってください:

  1. コレクションの作成:必要なフィールドを設定し、生テキストをスパース埋め込みに変換するBM25関数を定義します。

  2. データの挿入:生のテキスト文書をコレクションに取り込みます。

  3. 検索の実行:自然言語のクエリテキストを使用して、BM25の関連性に基づいてランク付けされた検索結果を取得します。

BM25を利用した全文検索を有効にするには、必要なフィールドを含むコレクションを準備し、スパースベクトルを生成するBM25関数を定義し、インデックスを設定した上で、コレクションを作成する必要があります。

スキーマフィールドの定義

コレクションのスキーマには、少なくとも以下の 3 つの必須フィールドを含める必要があります。

  • プライマリフィールド:コレクション内の各エンティティを一意に識別します。

  • 文字列フィールド(VARCHAR またはTEXT ):生のテキストドキュメントを格納します。MilvusがBM25の関連性ランキング用にテキストを処理できるよう、enable_analyzer=True を設定する必要があります。デフォルトでは、Milvusは standard アナライザーを使用します。別のアナライザーを設定するには、「アナライザーの概要」を参照してください。このページの例ではVARCHAR を使用しています。長いテキストの場合は、入力フィールドをTEXT として定義し、max_length を省略できます。完全な例については、「テキストフィールド」を参照してください。

  • スパースベクトルフィールド(SPARSE_FLOAT_VECTOR):BM25関数によって自動的に生成されたスパース埋め込みを格納します。

from pymilvus import MilvusClient, DataType, Function, FunctionType

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus"
)

schema = client.create_schema()

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True) # Primary field
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True) # Text field
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR) # Sparse vector field; no dim required for sparse vectors
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;

CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
        .build();
schema.addField(AddFieldReq.builder()
        .fieldName("id")
        .dataType(DataType.Int64)
        .isPrimaryKey(true)
        .autoID(true)
        .build());
schema.addField(AddFieldReq.builder()
        .fieldName("text")
        .dataType(DataType.VarChar)
        .maxLength(1000)
        .enableAnalyzer(true)
        .build());
schema.addField(AddFieldReq.builder()
        .fieldName("sparse")
        .dataType(DataType.SparseFloatVector)
        .build());
import (
    "context"
    "fmt"

    "github.com/milvus-io/milvus/client/v2/column"
    "github.com/milvus-io/milvus/client/v2/entity"
    "github.com/milvus-io/milvus/client/v2/index"
    "github.com/milvus-io/milvus/client/v2/milvusclient"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address: milvusAddr,
})
if err != nil {
    fmt.Println(err.Error())
    // handle error
}
defer client.Close(ctx)

schema := entity.NewSchema()
schema.WithField(entity.NewField().
    WithName("id").
    WithDataType(entity.FieldTypeInt64).
    WithIsPrimaryKey(true).
    WithIsAutoID(true),
).WithField(entity.NewField().
    WithName("text").
    WithDataType(entity.FieldTypeVarChar).
    WithEnableAnalyzer(true).
    WithMaxLength(1000),
).WithField(entity.NewField().
    WithName("sparse").
    WithDataType(entity.FieldTypeSparseVector),
)
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});
const schema = [
  {
    name: "id",
    data_type: DataType.Int64,
    is_primary_key: true,
  },
  {
    name: "text",
    data_type: "VarChar",
    enable_analyzer: true,
    enable_match: true,
    max_length: 1000,
  },
  {
    name: "sparse",
    data_type: DataType.SparseFloatVector,
  },
];

console.log(schema);
export schema='{
        "autoId": true,
        "enabledDynamicField": false,
        "fields": [
            {
                "fieldName": "id",
                "dataType": "Int64",
                "isPrimary": true
            },
            {
                "fieldName": "text",
                "dataType": "VarChar",
                "elementTypeParams": {
                    "max_length": 1000,
                    "enable_analyzer": true
                }
            },
            {
                "fieldName": "sparse",
                "dataType": "SparseFloatVector"
            }
        ]
    }'
#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();

milvus::ConnectParam connect_param{"http://localhost:19530", "root:Milvus"};
auto status = client->Connect(connect_param);
if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

milvus::CollectionSchemaPtr schema = std::make_shared<milvus::CollectionSchema>();
schema->AddField({"id", milvus::DataType::INT64, "", true, true});
schema->AddField(milvus::FieldSchema("text", milvus::DataType::VARCHAR).WithMaxLength(1000).EnableAnalyzer(true));
schema->AddField(milvus::FieldSchema("sparse", milvus::DataType::SPARSE_FLOAT_VECTOR));

前述の設定では、

  • id: は主キーとして機能し、auto_id=True によって自動的に生成されます。

  • text: 全文検索操作用の生のテキストデータを格納します。このフィールドでは、範囲が限定されたテキストの場合は `VARCHAR ` を、長いソースコンテンツの場合は `TEXT ` を使用できます。

  • sparse: 全文検索処理のために内部で生成されたスパース埋め込みを格納するために予約されたベクトルフィールドです。データ型はSPARSE_FLOAT_VECTOR でなければなりません。

BM25関数の定義

BM25関数は、トークン化されたテキストを、BM25スコアリングに対応した疎ベクトルに変換します。

関数を定義し、スキーマに追加します:

bm25_function = Function(
    name="text_bm25_emb", # Function name
    input_field_names=["text"], # Name of the VARCHAR or TEXT field containing raw text data
    output_field_names=["sparse"], # Name of the SPARSE_FLOAT_VECTOR field reserved to store generated embeddings
    function_type=FunctionType.BM25, # Set to `BM25`
)

schema.add_function(bm25_function)
import io.milvus.common.clientenum.FunctionType;
import io.milvus.v2.service.collection.request.CreateCollectionReq.Function;

import java.util.*;

schema.addFunction(Function.builder()
        .functionType(FunctionType.BM25)
        .name("text_bm25_emb")
        .inputFieldNames(Collections.singletonList("text"))
        .outputFieldNames(Collections.singletonList("sparse"))
        .build());
function := entity.NewFunction().
    WithName("text_bm25_emb").
    WithInputFields("text").
    WithOutputFields("sparse").
    WithType(entity.FunctionTypeBM25)
schema.WithFunction(function)
const functions = [
    {
      name: 'text_bm25_emb',
      description: 'bm25 function',
      type: FunctionType.BM25,
      input_field_names: ['text'],
      output_field_names: ['sparse'],
      params: {},
    },
];
export schema='{
        "autoId": true,
        "enabledDynamicField": false,
        "fields": [
            {
                "fieldName": "id",
                "dataType": "Int64",
                "isPrimary": true
            },
            {
                "fieldName": "text",
                "dataType": "VarChar",
                "elementTypeParams": {
                    "max_length": 1000,
                    "enable_analyzer": true
                }
            },
            {
                "fieldName": "sparse",
                "dataType": "SparseFloatVector"
            }
        ],
        "functions": [
            {
                "name": "text_bm25_emb",
                "type": "BM25",
                "inputFieldNames": ["text"],
                "outputFieldNames": ["sparse"],
                "params": {}
            }
        ]
    }'
milvus::FunctionPtr function = std::make_shared<milvus::Function>("text_bm25_emb", milvus::FunctionType::BM25);
function->AddInputFieldName("text");
function->AddOutputFieldName("sparse");
schema->AddFunction(function);

パラメータ

説明

name

関数の名前。この関数は、text フィールドの生のテキストを、BM25互換のスパースベクトルに変換し、sparse フィールドに格納します。

input_field_names

テキストからスパースベクトルへの変換が必要なVARCHAR またはTEXT フィールドの名前。FunctionType.BM25 の場合、このパラメータには1つのフィールド名のみ指定できます。

output_field_names

内部で生成されたスパースベクトルが格納されるフィールドの名前。FunctionType.BM25 の場合、このパラメータには1つのフィールド名のみ指定できます。

function_type

使用する関数のタイプ。FunctionType.BM25 でなければなりません。

複数のテキストフィールドで BM25 処理が必要な場合は、フィールドごとに 1 つの BM25 関数を定義し、それぞれに一意の名前と出力フィールドを指定します。

インデックスの設定

必要なフィールドと組み込み関数を使用してスキーマを定義した後、コレクションのインデックスを設定します。

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="sparse",

    index_type="SPARSE_INVERTED_INDEX",
    metric_type="BM25",
    params={
        "inverted_index_algo": "DAAT_MAXSCORE",
        "bm25_k1": 1.2,
        "bm25_b": 0.75
    }

)
import io.milvus.v2.common.IndexParam;

Map<String,Object> params = new HashMap<>();
params.put("inverted_index_algo", "DAAT_MAXSCORE");
params.put("bm25_k1", 1.2);
params.put("bm25_b", 0.75);

List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
        .fieldName("sparse")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .metricType(IndexParam.MetricType.BM25)
        .extraParams(params)
        .build());    
indexOption := milvusclient.NewCreateIndexOption("my_collection", "sparse",
    index.NewAutoIndex(entity.MetricType(entity.BM25)))
    .WithExtraParam("inverted_index_algo", "DAAT_MAXSCORE")
    .WithExtraParam("bm25_k1", 1.2)
    .WithExtraParam("bm25_b", 0.75)
const index_params = [
  {
    field_name: "sparse",
    metric_type: "BM25",
    index_type: "SPARSE_INVERTED_INDEX",
    params: {
        "inverted_index_algo": "DAAT_MAXSCORE",
        "bm25_k1": 1.2,
        "bm25_b": 0.75
    }
  },
];
export indexParams='[
        {
            "fieldName": "sparse",
            "metricType": "BM25",
            "indexType": "AUTOINDEX",
            "params":{
               "inverted_index_algo": "DAAT_MAXSCORE",
               "bm25_k1": 1.2,
               "bm25_b": 0.75
            }
        }
    ]'
auto index_params = milvus::IndexDesc("sparse", "", milvus::IndexType::SPARSE_INVERTED_INDEX, milvus::MetricType::BM25);
index_params.AddExtraParam("inverted_index_algo", "DAAT_MAXSCORE");
index_params.AddExtraParam("bm25_k1", "1.2");
index_params.AddExtraParam("bm25_b", "0.75");

パラメータ

説明

field_name

インデックス化するベクトルフィールドの名前。全文検索の場合、これは生成されたスパースベクトルが格納されるフィールドである必要があります。この例では、値を `sparse` に設定します。

index_type

作成するインデックスのタイプ。MilvusでのBM25全文検索を行う場合は、この値をSPARSE_INVERTED_INDEX に設定します。詳細については、SPARSE_INVERTED_INDEXを参照してください。

metric_type

このパラメータの値は、全文検索機能を使用する場合に限り、BM25 に設定する必要があります。

params

インデックス固有の追加パラメータの辞書。

params.inverted_index_algo

BM25 スパース反転インデックスの構築およびクエリ実行に使用されるアルゴリズム。有効な値:

  • "DAAT_MAXSCORE" (デフォルト): Document-at-a-Time MaxScore クエリ処理。このオプションは、k値が大きい全文検索ワークロードや、多くの検索語を含むクエリに適しています。背景については、「クエリ評価: 戦略と最適化」を参照してください。

  • "DAAT_WAND": Document-at-a-Time WAND クエリ処理。このオプションは、k値が小さい、またはクエリが短い全文検索ワークロードに適しています。背景については、「2 段階検索プロセスによる効率的なクエリ評価」を参照してください。

  • "TAAT_NAIVE": 基本的な「Term-at-a-Time」クエリ処理。このオプションは、ベースラインとして、または平均ドキュメント長などのコレクション全体の統計情報に合わせてスコアリングを動的に調整する必要がある場合に使用します。

  • "BLOCK_MAX_MAXSCORE": ブロックレベルの最大スコアメタデータを用いた MaxScore クエリ処理。背景については、「Block-Max インデックスを用いた高速なトップ k ドキュメント検索」を参照してください。

  • "BLOCK_MAX_WAND": ブロックレベルの最大スコア・メタデータを用いた WAND クエリ処理。背景については、「Block-Max インデックスを用いた高速な Top-k ドキュメント検索」を参照してください。

params.bm25_k1

用語頻度の飽和度を制御します。値が大きいほど、ドキュメントのランキングにおける用語頻度の重要度が高まります。推奨範囲:[1.2, 2.0]。デフォルト値:1.2。

params.bm25_b

文書の長さを正規化する程度を制御します。通常、0 から 1 までの値が使用され、デフォルト値は 0.75 です。値が 0 の場合は長さの正規化が行われず、値が 1 の場合は完全な長さの正規化が行われます。

コレクションの作成

定義したスキーマとインデックスパラメータを使用して、コレクションを作成します。

client.create_collection(
    collection_name='my_collection', 
    schema=schema, 
    index_params=index_params
)
import io.milvus.v2.service.collection.request.CreateCollectionReq;

CreateCollectionReq requestCreate = CreateCollectionReq.builder()
        .collectionName("my_collection")
        .collectionSchema(schema)
        .indexParams(indexes)
        .build();
client.createCollection(requestCreate);
err = client.CreateCollection(ctx,
    milvusclient.NewCreateCollectionOption("my_collection", schema).
        WithIndexOptions(indexOption))
if err != nil {
    fmt.Println(err.Error())
    // handle error
}
await client.create_collection({
    collection_name: 'my_collection',
    schema: schema,
    index_params: index_params,
    functions: functions
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
    \"collectionName\": \"my_collection\",
    \"schema\": $schema,
    \"indexParams\": $indexParams
}"
auto status = client->CreateCollection(milvus::CreateCollectionRequest()
                                    .WithCollectionName("my_collection")
                                    .WithCollectionSchema(schema)
                                    .AddIndex(std::move(index_params)));
if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

テキストデータの挿入

コレクションとインデックスの設定が完了したら、テキストデータの挿入準備が整います。このプロセスでは、生のテキストを指定するだけで済みます。先ほど定義した組み込み関数が、各テキストエントリに対応するスパースベクトルを自動的に生成します。

client.insert('my_collection', [
    {'text': 'information retrieval is a field of study.'},
    {'text': 'information retrieval focuses on finding relevant information in large datasets.'},
    {'text': 'data mining and information retrieval overlap in research.'},
])
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import io.milvus.v2.service.vector.request.InsertReq;

Gson gson = new Gson();
List<JsonObject> rows = Arrays.asList(
        gson.fromJson("{\"text\": \"information retrieval is a field of study.\"}", JsonObject.class),
        gson.fromJson("{\"text\": \"information retrieval focuses on finding relevant information in large datasets.\"}", JsonObject.class),
        gson.fromJson("{\"text\": \"data mining and information retrieval overlap in research.\"}", JsonObject.class)
);

client.insert(InsertReq.builder()
        .collectionName("my_collection")
        .data(rows)
        .build());
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
    WithVarcharColumn("text", []string{
        "information retrieval is a field of study.",
        "information retrieval focuses on finding relevant information in large datasets.",
        "data mining and information retrieval overlap in research.",
    }),
)
if err != nil {
    fmt.Println(err.Error())
    // handle error
}
await client.insert({
    collection_name: 'my_collection',
    data: [
        {'text': 'information retrieval is a field of study.'},
        {'text': 'information retrieval focuses on finding relevant information in large datasets.'},
        {'text': 'data mining and information retrieval overlap in research.'},
    ],
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
    "data": [
        {"text": "information retrieval is a field of study."},
        {"text": "information retrieval focuses on finding relevant information in large datasets."},
        {"text": "data mining and information retrieval overlap in research."}       
    ],
    "collectionName": "my_collection"
}'

milvus::EntityRows data = {
    {{"text", "information retrieval is a field of study."}},
    {{"text", "information retrieval focuses on finding relevant information in large datasets."}},
    {{"text", "data mining and information retrieval overlap in research."}}
};

milvus::InsertResponse response;
auto status = client->Insert(milvus::InsertRequest()
                                .WithCollectionName("my_collection")
                                .WithRowsData(std::move(data))
                                , response);
if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

コレクションにデータを挿入すると、生のテキストクエリを使用して全文検索を実行できます。Milvusはクエリを自動的にスパースベクトルに変換し、BM25アルゴリズムを使用して一致した検索結果をランク付けした後、topK(limit )の結果を返します。

テキストハイライターを設定することで、検索結果内の一致した用語をハイライト表示できます。詳細については、「テキストハイライター」を参照してください。

res = client.search(
    collection_name='my_collection', 
    data=['whats the focus of information retrieval?'],
    anns_field='sparse',
    output_fields=['text'], # Fields to return in search results; sparse field cannot be output
    limit=3,
)

print(res)
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.EmbeddedText;
import io.milvus.v2.service.vector.response.SearchResp;

Map<String,Object> searchParams = new HashMap<>();

SearchResp searchResp = client.search(SearchReq.builder()
        .collectionName("my_collection")
        .data(Collections.singletonList(new EmbeddedText("whats the focus of information retrieval?")))
        .annsField("sparse")
        .topK(3)
        .searchParams(searchParams)
        .outputFields(Collections.singletonList("text"))
        .build());
annSearchParams := index.NewCustomAnnParam()
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
    "my_collection", // collectionName
    3,               // limit
    []entity.Vector{entity.Text("whats the focus of information retrieval?")},
).WithConsistencyLevel(entity.ClStrong).
    WithANNSField("sparse").
    WithAnnParam(annSearchParams).
    WithOutputFields("text"))
if err != nil {
    fmt.Println(err.Error())
    // handle error
}

for _, resultSet := range resultSets {
    fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
    fmt.Println("Scores: ", resultSet.Scores)
    fmt.Println("text: ", resultSet.GetColumn("text").FieldData().GetScalars())
}
await client.search({
    collection_name: 'my_collection',
    data: ['whats the focus of information retrieval?'],
    anns_field: 'sparse',
    output_fields: ['text'],
    limit: 3,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
--data-raw '{
    "collectionName": "my_collection",
    "data": [
        "whats the focus of information retrieval?"
    ],
    "annsField": "sparse",
    "limit": 3,
    "outputFields": [
        "text"
    ],
    "searchParams":{
        "params":{}
    }
}'
auto request = milvus::SearchRequest()
                       .WithCollectionName("my_collection")
                       .AddEmbeddedText("whats the focus of information retrieval?")
                       .WithLimit(3)
                       .WithAnnsField("sparse")
                       .AddOutputField("text");

milvus::SearchResponse response;
auto status = client->Search(request, response);
if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

パラメータ

説明

search_params

検索パラメータを含む辞書。

params.drop_ratio_search

検索時に無視する重要度の低い用語の割合。値は [0.0, 1.0) の範囲で指定する必要があります。詳細については、「スパースベクトル」を参照してください。

data

自然言語による生のクエリテキスト。MilvusはBM25関数を使用してテキストクエリを自動的にスパースベクトルに変換します。事前に計算済みのベクトルを指定しないでください。

anns_field

内部で生成されたスパースベクトルが格納されるフィールド名。

output_fields

検索結果に返すフィールド名のリスト。BM25 で生成された埋め込みを含むスパースベクトルフィールドを除く、すべてのフィールドをサポートしています。一般的な出力フィールドには、主キーフィールド(例:id )や元のテキストフィールド(例:text )などがあります。詳細については、FAQ を参照してください。

limit

返す上位一致件数の最大値。

FAQ

いいえ、フルテキスト検索において、BM25関数によって生成されたスパースベクトルに直接アクセスしたり、出力したりすることはできません。詳細は以下の通りです:

  • BM25 関数は、ランキングおよび検索のために内部でスパースベクトルを生成します。

  • これらのベクトルはスパースフィールドに格納されますが、output_fields

  • 出力できるのは、元のテキストフィールドとメタデータ(id 、text など)のみです

例:

# ❌ This throws an error - you cannot output the sparse field
client.search(
    collection_name='my_collection',
    data=['query text'],
    anns_field='sparse',
    output_fields=['text', 'sparse'],  # 'sparse' causes an error
    limit=3,
    search_params=search_params
)

# ✅ This works - output text fields only
client.search(
    collection_name='my_collection',
    data=['query text'],
    anns_field='sparse',
    output_fields=['text'],
    limit=3,
    search_params=search_params
)
// Searching with the sparse field in outputFields throws an error.
// Only output the original text and metadata fields.
SearchResp searchResp = client.search(SearchReq.builder()
        .collectionName("my_collection")
        .data(Collections.singletonList(new EmbeddedText("query text")))
        .annsField("sparse")
        .topK(3)
        .outputFields(Collections.singletonList("text"))
        .build());
// Searching with the sparse field in output_fields throws an error.
// Only output the original text and metadata fields.
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
    "my_collection",
    3,
    []entity.Vector{entity.Text("query text")},
).WithConsistencyLevel(entity.ClStrong).
    WithANNSField("sparse").
    WithAnnParam(index.NewCustomAnnParam()).
    WithOutputFields("text"))
// Searching with the sparse field in output_fields throws an error.
// Only output the original text and metadata fields.
await client.search({
    collection_name: 'my_collection',
    data: ['query text'],
    anns_field: 'sparse',
    output_fields: ['text'],
    limit: 3,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
--data-raw '{
    "collectionName": "my_collection",
    "data": ["query text"],
    "annsField": "sparse",
    "limit": 3,
    "outputFields": ["text"]
}'
// Searching with the sparse field in output_fields throws an error.
// Only output the original text and metadata fields.
milvus::SearchRequest request = milvus::SearchRequest()
    .WithCollectionName("my_collection")
    .AddEmbeddedText("query text")
    .WithLimit(3)
    .WithAnnsField("sparse")
    .AddOutputField("text");

アクセスできないのになぜスパースベクトルフィールドを定義する必要があるのですか?

スパースベクトルフィールドは、ユーザーが直接操作することのないデータベースのインデックスと同様に、内部的な検索インデックスとして機能します。

設計の根拠:

  • 関心の分離:ユーザーはテキスト(入力/出力)を扱い、Milvusはベクトル(内部処理)を処理します

  • パフォーマンス:事前に計算されたスパースベクトルにより、クエリ実行時のBM25ランキング処理が高速化されます

  • ユーザー体験:単純なテキストインターフェースの背後で、複雑なベクトル演算を抽象化しています

ベクトルへのアクセスが必要な場合:

  • 全文検索の代わりに、手動によるスパースベクトル操作を使用してください

  • カスタム疎ベクトルワークフロー用に個別のコレクションを作成してください

詳細については、「スパースベクトル」を参照してください。