...
querynode reads segment's binlog files from Minio, and saves them into structure Blob (internal/querynode/segment_loader.go::loadSegmentFieldsData)
Code Block type Blob struct { Key string // binlog file path Value []byte // binlog file data }
The data in Blob is deserialized, raw-data in it is saved into structure InsertData
querynode invokes search engine to get SearchResult (internal/query_node/query_collection.go::search)
Code Block language cpp // internal/core/src/common/Types.h struct SearchResult { ... public: int64_t num_queries_; int64_t topk_; std::vector<float> result_distances_; public: void* segment_; std::vector<int64_t> internal_seg_offsets_; std::vector<int64_t> result_offsets_; std::vector<std::vector<char>> row_data_; };
At this time, only "result_distances_" and "internal_seg_offsets_" of "SearchResult" are filled into data.querynode reduces all SearchResult returned by segment, fetches all other fields' data, and saves them into "row_data_" with row-based format. (internal/query_node/query_collection.go::reduceSearchResultsAndFillData)
querynode organizes SearchResult again, and save them into structure milvus.Hits
Code Block // internal/proto/milvus.proto message Hits { repeated int64 IDs = 1; repeated bytes row_data = 2; repeated float scores = 3; }
Row-based data saved in milvus.Hits is converted to column-based data, and saved into schemapb.SearchResultData (internal/query_node/query_collection.go::translateHits)
Code Block // internal/proto/schema.proto message SearchResultData { int64 num_queries = 1; int64 top_k = 2; repeated FieldData fields_data = 3; repeated float scores = 4; IDs ids = 5; repeated int64 topks = 6; }
- schemapb.SearchResultData 被序列化后,封装为 is serialized, encapsulated as internalpb.SearchResults,并放入
msgstream.SearchResultMsg
,通过 , saved into SearchResultMsg, and send into pulsar channel 发送 (internal/query_node/query_collection.go::search)Code Block // internal/proto/internal.proto
message SearchResults {
commoncommon.MsgBase base = 1;
commoncommon.Status status = 2;
stringstring result_channelID = 3;
stringstring metric_type = 4;
repeatedrepeated bytes hits = 5; // search result data
// schema.SearchResultsData inside
bytesbytes sliced_blob = 9;
int64int64 sliced_num_count = 10;
int64int64 sliced_offset = 11;
repeatedrepeated int64 sealed_segmentIDs_searched = 6;
repeatedrepeated string channelIDs_searched = 7;
repeatedrepeated int64 global_sealed_segmentIDs = 8;
}
proxy
从 pulsar channel 中收集到所有querynode
发送过来的msgstream.SearchResultMsg
,反序列化得到schemapb.SearchResultData
,再做一次归并,数据放入milvuspb.SearchResults
,通过 gRPC 传回 SDK (internal/proxy/task.go::SearchTask::PostExecute)// internal/proto/milvus.proto
message SearchResults {
common.Status status = 1;
schema.SearchResultData results = 2;
}SDK 收到
milvuspb.SearchResults
...