You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Doris executes Lance full-text search in a distributed architecture. The FE plans one query and assigns different Lance fragments or FTS index segments to multiple BEs.
If each BE builds BM25 statistics from only its local segments, its document count, total token count, average document length, and query-term document frequencies can differ from other workers. Those worker-local scores are not comparable, and merging local Top-K results cannot recover the ranking produced by one search over the complete index.
The FE Java layer therefore needs to collect query-bound, corpus-wide BM25 statistics for one pinned Lance dataset snapshot. The FE stores the resulting opaque payload in TFullTextSearchParams.global_statistics. That field is delivered directly to every BE through the existing TLanceScanParams.external_search_request Thrift scan plan; this design does not introduce a separate broadcast or coordination channel.
flowchart TB
subgraph FE["Doris FE - Java query planning"]
Q["FTS query"] --> P["Pin Lance dataset version<br/>resolve complete FTS segment set"]
P --> J["Lance Java API<br/>collect global BM25 statistics"]
J --> T["Set TFullTextSearchParams.global_statistics"]
M["Merge comparable BE Top-K results"]
end
subgraph LANCE["One logical Lance FTS index"]
S1["FTS segment 1"]
S2["FTS segment 2"]
S3["FTS segment 3"]
end
T --> THRIFT["Existing Thrift scan-plan delivery"]
subgraph BES["Doris BE cluster"]
BE1["BE 1<br/>consume global statistics<br/>search assigned segments"]
BE2["BE 2<br/>consume global statistics<br/>search assigned segments"]
BE3["BE 3<br/>consume global statistics<br/>search assigned segments"]
end
S1 --> J
S2 --> J
S3 --> J
THRIFT --> BE1
THRIFT --> BE2
THRIFT --> BE3
BE1 --> M
BE2 --> M
BE3 --> M
Loading
V1 scope
The first version deliberately represents one BM25 corpus:
one dataset version;
one logical FTS index, indexed column, and document granularity;
the exact committed segment UUID set for that corpus;
corpus document count, total token count, and document frequency for every prepared term;
the prepared vocabulary and original token positions for every scoring leaf, including fuzzy expansion.
Every scoring leaf must resolve to the same corpus. Cross-column or otherwise cross-corpus queries must be rejected.
The protobuf is an opaque payload within a trusted planning flow. The FE must attach it only to the same query used to produce it. Consumers validate the schema and dataset/index metadata, but V1 does not attempt to reconstruct and independently prove the original query identity.
Existing Doris integration point
PR #67289 reserves TFullTextSearchParams.global_statistics as an optional opaque binary field. The FE creates the ScanNode-level external_search_request, and the BE receives the same request from TFileScanRangeParams.lance_scan_params.
The BE currently returns an unsupported error when global_statistics is present because the lance-c consumer API is not available yet.
These PRs provide the FE-side producer. A follow-up Rust/lance-c consumer is still required before the Doris BE can apply the payload to its assigned segment subset.
Remaining work
Merge the Lance protobuf and producer PRs.
Add the Rust/lance-c consumer that validates the payload and installs the prepared BM25 context before FTS execution.
Make the Doris FE populate TFullTextSearchParams.global_statistics through the Java API.
Make each Doris BE consume the field through lance-c for its assigned segments.
Define the behavior for unindexed fragments and mixed indexed/unindexed execution.
Completion criteria
Distributed FTS ranking matches a single full-index execution over the same dataset version and committed segment set.
Regression tests cover multiple segments where worker-local and global BM25 statistics produce different rankings.
Fuzzy queries replay the same globally prepared vocabulary and token positions.
Unsupported cross-corpus queries fail with a clear error.
EXPLAIN or runtime profiles show whether FE-provided global BM25 statistics are used.
Parent
Motivation
Doris executes Lance full-text search in a distributed architecture. The FE plans one query and assigns different Lance fragments or FTS index segments to multiple BEs.
If each BE builds BM25 statistics from only its local segments, its document count, total token count, average document length, and query-term document frequencies can differ from other workers. Those worker-local scores are not comparable, and merging local Top-K results cannot recover the ranking produced by one search over the complete index.
The FE Java layer therefore needs to collect query-bound, corpus-wide BM25 statistics for one pinned Lance dataset snapshot. The FE stores the resulting opaque payload in
TFullTextSearchParams.global_statistics. That field is delivered directly to every BE through the existingTLanceScanParams.external_search_requestThrift scan plan; this design does not introduce a separate broadcast or coordination channel.flowchart TB subgraph FE["Doris FE - Java query planning"] Q["FTS query"] --> P["Pin Lance dataset version<br/>resolve complete FTS segment set"] P --> J["Lance Java API<br/>collect global BM25 statistics"] J --> T["Set TFullTextSearchParams.global_statistics"] M["Merge comparable BE Top-K results"] end subgraph LANCE["One logical Lance FTS index"] S1["FTS segment 1"] S2["FTS segment 2"] S3["FTS segment 3"] end T --> THRIFT["Existing Thrift scan-plan delivery"] subgraph BES["Doris BE cluster"] BE1["BE 1<br/>consume global statistics<br/>search assigned segments"] BE2["BE 2<br/>consume global statistics<br/>search assigned segments"] BE3["BE 3<br/>consume global statistics<br/>search assigned segments"] end S1 --> J S2 --> J S3 --> J THRIFT --> BE1 THRIFT --> BE2 THRIFT --> BE3 BE1 --> M BE2 --> M BE3 --> MV1 scope
The first version deliberately represents one BM25 corpus:
Every scoring leaf must resolve to the same corpus. Cross-column or otherwise cross-corpus queries must be rejected.
The protobuf is an opaque payload within a trusted planning flow. The FE must attach it only to the same query used to produce it. Consumers validate the schema and dataset/index metadata, but V1 does not attempt to reconstruct and independently prove the original query identity.
Existing Doris integration point
PR #67289 reserves
TFullTextSearchParams.global_statisticsas an optional opaque binary field. The FE creates the ScanNode-levelexternal_search_request, and the BE receives the same request fromTFileScanRangeParams.lance_scan_params.The BE currently returns an unsupported error when
global_statisticsis present because the lance-c consumer API is not available yet.Upstream Lance work
These PRs provide the FE-side producer. A follow-up Rust/lance-c consumer is still required before the Doris BE can apply the payload to its assigned segment subset.
Remaining work
TFullTextSearchParams.global_statisticsthrough the Java API.Completion criteria