diff --git a/src/fastfield/readers.rs b/src/fastfield/readers.rs index fa3c44038..45564170c 100644 --- a/src/fastfield/readers.rs +++ b/src/fastfield/readers.rs @@ -87,8 +87,7 @@ impl FastFieldReaders { ) -> crate::Result> { let Some((field, path)): Option<(Field, &str)> = self .schema - .find_field(field_name) - .or_else(|| default_field_opt.map(|default_field| (default_field, field_name))) + .find_field_with_default(field_name, default_field_opt) else{ return Ok(None); }; @@ -98,22 +97,17 @@ impl FastFieldReaders { "Field {field_name:?} is not configured as fast field" ))); } - let field_name = self.schema.get_field_name(field); - if path.is_empty() { - return Ok(Some(field_name.to_string())); - } - let field_type = field_entry.field_type(); - match (field_type, path) { + Ok(match (field_entry.field_type(), path) { (FieldType::JsonObject(json_options), path) if !path.is_empty() => { - Ok(Some(encode_column_name( + Some(encode_column_name( field_entry.name(), path, json_options.is_expand_dots_enabled(), - ))) + )) } - (_, "") => Ok(Some(field_entry.name().to_string())), - _ => Ok(None), - } + (_, "") => Some(field_entry.name().to_string()), + _ => None, + }) } /// Returns a typed column associated to a given field name. diff --git a/src/schema/schema.rs b/src/schema/schema.rs index bb98aa4bf..9b10376f2 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -410,6 +410,30 @@ impl Schema { } None } + + /// Transforms a user-supplied fast field name into a column name. + /// + /// This is similar to `.find_field` except it includes some fallback logic to + /// a default json field. This functionality is used in Quickwit. + /// + /// If the remaining path is empty and seems to target JSON field, we return None. + /// If the remaining path is non-empty and seems to target a non-JSON field, we return None. + #[doc(hidden)] + pub fn find_field_with_default<'a>( + &self, + full_path: &'a str, + default_field_opt: Option, + ) -> Option<(Field, &'a str)> { + let (field, json_path) = self + .find_field(full_path) + .or(default_field_opt.and_then(|field| Some((field, full_path))))?; + let field_entry = self.get_field_entry(field); + let is_json = field_entry.field_type().value_type() == Type::Json; + if is_json == json_path.is_empty() { + return None; + } + Some((field, json_path)) + } } impl Serialize for Schema {