Summary
Collection-scoped text searches currently perform an additional GET /collections/{name} call whenever q is present and query_by is omitted, in order to auto-populate query_by from searchable_fields. This creates a hidden extra network round-trip on the hottest path in the client and can materially degrade latency and throughput for search-heavy workloads.
Context
The auto-detection logic exists in both [src/collections.cpp] and [src/search.cpp]. In Collections::search(...) and Search::search(...), the client fetches collection metadata before issuing the actual search request if query_by is missing.
That behavior is convenient, but it is expensive for a high-performance search engine wrapper:
- A single logical search can become two HTTP requests.
- Repeated searches against the same collection repeatedly re-fetch identical schema metadata.
- Recent API additions around collection-scoped search and the
like alias make this path more central, so the hidden overhead is more likely to affect normal usage.
- If the metadata request fails transiently, the client silently loses the optimization and search behavior becomes dependent on an unrelated control-plane call.
This is especially problematic for low-latency services, batch search workloads, and any deployment where the client and server communicate over a network boundary.
Proposed Implementation
- Add an internal per-collection cache of
searchable_fields, owned by Collections and reused by the search flow.
- On the first search without
query_by, fetch collection metadata once, derive the comma-separated query_by, and store it in the cache.
- Reuse the cached value for subsequent searches against the same collection.
- Invalidate or refresh the cache on collection mutation paths such as create, update, and remove.
- Keep an escape hatch:
- either a client option to disable implicit
query_by inference entirely, or
- a dedicated method to prewarm/refresh collection schema metadata explicitly.
- Refactor the duplicated inference logic so
Search and Collections share one implementation path.
Impact
This removes an avoidable request from a core search path, which should reduce end-to-end latency, cut control-plane load, and improve throughput under sustained search traffic. It also makes client behavior more predictable by separating schema discovery from the execution of the actual query.
Summary
Collection-scoped text searches currently perform an additional
GET /collections/{name}call wheneverqis present andquery_byis omitted, in order to auto-populatequery_byfromsearchable_fields. This creates a hidden extra network round-trip on the hottest path in the client and can materially degrade latency and throughput for search-heavy workloads.Context
The auto-detection logic exists in both [
src/collections.cpp] and [src/search.cpp]. InCollections::search(...)andSearch::search(...), the client fetches collection metadata before issuing the actual search request ifquery_byis missing.That behavior is convenient, but it is expensive for a high-performance search engine wrapper:
likealias make this path more central, so the hidden overhead is more likely to affect normal usage.This is especially problematic for low-latency services, batch search workloads, and any deployment where the client and server communicate over a network boundary.
Proposed Implementation
searchable_fields, owned byCollectionsand reused by the search flow.query_by, fetch collection metadata once, derive the comma-separatedquery_by, and store it in the cache.query_byinference entirely, orSearchandCollectionsshare one implementation path.Impact
This removes an avoidable request from a core search path, which should reduce end-to-end latency, cut control-plane load, and improve throughput under sustained search traffic. It also makes client behavior more predictable by separating schema discovery from the execution of the actual query.