mirror of
https://github.com/lancedb/lancedb.git
synced 2026-09-21 20:45:57 +00:00
fix: expose public FTS paths in remote index listings (#4194)
Remote `list_indices()` exposes physical FTS paths such as `docs.item.content`, while index creation, queries, and native table listings use `docs.content`. Normalize FTS columns to the public path after parsing the server response, using the same field-ID-based conversion as native tables. Keep the physical paths on the wire: existing clients need them to resolve the Arrow schema. Cover both legacy responses that fetch index statistics and enriched responses that already include the index type.
This commit is contained in:
@@ -43,8 +43,8 @@ use crate::table::{
|
||||
use crate::table::{AnyQuery, Filter, Predicate, PreprocessingOutput, TableStatistics};
|
||||
use crate::utils::background_cache::BackgroundCache;
|
||||
use crate::utils::{
|
||||
MaxBatchLengthStream, TimeoutStream, resolve_arrow_field_path, resolve_arrow_fts_field_path,
|
||||
supported_btree_data_type, supported_vector_data_type,
|
||||
MaxBatchLengthStream, TimeoutStream, public_fts_field_path_by_id, resolve_arrow_field_path,
|
||||
resolve_arrow_fts_field_path, supported_btree_data_type, supported_vector_data_type,
|
||||
};
|
||||
use crate::{DistanceType, Error};
|
||||
use crate::{
|
||||
@@ -2042,7 +2042,19 @@ impl<S: HttpSend + 'static> RemoteTable<S> {
|
||||
}
|
||||
|
||||
let results = futures::future::try_join_all(futures).await?;
|
||||
Ok(results.into_iter().flatten().collect())
|
||||
let mut indices: Vec<IndexConfig> = results.into_iter().flatten().collect();
|
||||
let lance_schema = lance_core::datatypes::Schema::try_from(schema.as_ref())?;
|
||||
for index in &mut indices {
|
||||
if index.index_type == IndexType::FTS {
|
||||
// The wire format uses physical paths for schema resolution. Match
|
||||
// native tables by exposing list-transparent paths to callers.
|
||||
for column in &mut index.columns {
|
||||
let field_id = lance_schema.field_id(column)?;
|
||||
*column = public_fts_field_path_by_id(&lance_schema, field_id)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(indices)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6984,6 +6996,43 @@ mod tests {
|
||||
assert_eq!(indices, expected);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::legacy(false)]
|
||||
#[case::enriched(true)]
|
||||
#[tokio::test]
|
||||
async fn test_list_indices_fts_public_list_path(#[case] enriched: bool) {
|
||||
let schema = nested_index_schema();
|
||||
let table = Table::new_with_handler("my_table", move |request| {
|
||||
let body = match request.url().path() {
|
||||
"/v1/table/my_table/describe/" => describe_response(&schema),
|
||||
"/v1/table/my_table/index/list/" => serde_json::json!({
|
||||
"indexes": [{
|
||||
"index_name": "docs_idx",
|
||||
"columns": ["docs.item.content"],
|
||||
"index_type": enriched.then_some("FTS"),
|
||||
}],
|
||||
})
|
||||
.to_string(),
|
||||
"/v1/table/my_table/index/docs_idx/stats/" => {
|
||||
assert!(!enriched, "enriched responses must not fetch index stats");
|
||||
serde_json::json!({
|
||||
"num_indexed_rows": 1,
|
||||
"num_unindexed_rows": 0,
|
||||
"index_type": "FTS",
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
path => panic!("Unexpected path: {path}"),
|
||||
};
|
||||
http::Response::builder().status(200).body(body).unwrap()
|
||||
});
|
||||
|
||||
let indices = table.list_indices().await.unwrap();
|
||||
assert_eq!(indices.len(), 1);
|
||||
assert_eq!(indices[0].index_type, IndexType::FTS);
|
||||
assert_eq!(indices[0].columns, vec!["docs.content"]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_indices_nested_field_paths() {
|
||||
let schema = nested_index_schema();
|
||||
|
||||
Reference in New Issue
Block a user