Add field.is_searchable property to fields

This commit is contained in:
Louis Dureuil 2024-09-02 11:28:53 +02:00
parent 9a756cf2c5
commit 915cf4bae5
No known key found for this signature in database
3 changed files with 58 additions and 10 deletions

View File

@ -5,7 +5,7 @@ use liquid::{ObjectView, ValueView};
use super::document::Document; use super::document::Document;
use super::fields::Fields; use super::fields::Fields;
use crate::FieldsIdsMap; use super::FieldsIdsMapWithMetadata;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Context<'a> { pub struct Context<'a> {
@ -14,7 +14,7 @@ pub struct Context<'a> {
} }
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub fn new(document: &'a Document<'a>, field_id_map: &'a FieldsIdsMap) -> Self { pub fn new(document: &'a Document<'a>, field_id_map: &'a FieldsIdsMapWithMetadata<'a>) -> Self {
Self { document, fields: Fields::new(document, field_id_map) } Self { document, fields: Fields::new(document, field_id_map) }
} }
} }

View File

@ -4,16 +4,20 @@ use liquid::model::{
use liquid::{ObjectView, ValueView}; use liquid::{ObjectView, ValueView};
use super::document::Document; use super::document::Document;
use crate::FieldsIdsMap; use super::{FieldMetadata, FieldsIdsMapWithMetadata};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Fields<'a>(Vec<FieldValue<'a>>); pub struct Fields<'a>(Vec<FieldValue<'a>>);
impl<'a> Fields<'a> { impl<'a> Fields<'a> {
pub fn new(document: &'a Document<'a>, field_id_map: &'a FieldsIdsMap) -> Self { pub fn new(document: &'a Document<'a>, field_id_map: &'a FieldsIdsMapWithMetadata<'a>) -> Self {
Self( Self(
std::iter::repeat(document) std::iter::repeat(document)
.zip(field_id_map.iter()) .zip(field_id_map.iter())
.map(|(document, (_fid, name))| FieldValue { document, name }) .map(|(document, (fid, name))| FieldValue {
document,
name,
metadata: field_id_map.metadata(fid).unwrap_or_default(),
})
.collect(), .collect(),
) )
} }
@ -23,6 +27,7 @@ impl<'a> Fields<'a> {
pub struct FieldValue<'a> { pub struct FieldValue<'a> {
name: &'a str, name: &'a str,
document: &'a Document<'a>, document: &'a Document<'a>,
metadata: FieldMetadata,
} }
impl<'a> ValueView for FieldValue<'a> { impl<'a> ValueView for FieldValue<'a> {
@ -74,6 +79,10 @@ impl<'a> FieldValue<'a> {
self.document.get(self.name).unwrap_or(&LiquidValue::Nil) self.document.get(self.name).unwrap_or(&LiquidValue::Nil)
} }
pub fn is_searchable(&self) -> &bool {
&self.metadata.searchable
}
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.size() == 0 self.size() == 0
} }
@ -89,12 +98,14 @@ impl<'a> ObjectView for FieldValue<'a> {
} }
fn keys<'k>(&'k self) -> Box<dyn Iterator<Item = KStringCow<'k>> + 'k> { fn keys<'k>(&'k self) -> Box<dyn Iterator<Item = KStringCow<'k>> + 'k> {
Box::new(["name", "value"].iter().map(|&x| KStringCow::from_static(x))) Box::new(["name", "value", "is_searchable"].iter().map(|&x| KStringCow::from_static(x)))
} }
fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k> { fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k> {
Box::new( Box::new(
std::iter::once(self.name() as &dyn ValueView).chain(std::iter::once(self.value())), std::iter::once(self.name() as &dyn ValueView)
.chain(std::iter::once(self.value()))
.chain(std::iter::once(self.is_searchable() as &dyn ValueView)),
) )
} }
@ -103,13 +114,14 @@ impl<'a> ObjectView for FieldValue<'a> {
} }
fn contains_key(&self, index: &str) -> bool { fn contains_key(&self, index: &str) -> bool {
index == "name" || index == "value" index == "name" || index == "value" || index == "is_searchable"
} }
fn get<'s>(&'s self, index: &str) -> Option<&'s dyn ValueView> { fn get<'s>(&'s self, index: &str) -> Option<&'s dyn ValueView> {
match index { match index {
"name" => Some(self.name()), "name" => Some(self.name()),
"value" => Some(self.value()), "value" => Some(self.value()),
"is_searchable" => Some(self.is_searchable()),
_ => None, _ => None,
} }
} }

View File

@ -4,14 +4,16 @@ pub(crate) mod error;
mod fields; mod fields;
mod template_checker; mod template_checker;
use std::collections::BTreeMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::Deref;
use error::{NewPromptError, RenderPromptError}; use error::{NewPromptError, RenderPromptError};
use self::context::Context; use self::context::Context;
use self::document::Document; use self::document::Document;
use crate::update::del_add::DelAdd; use crate::update::del_add::DelAdd;
use crate::FieldsIdsMap; use crate::{FieldId, FieldsIdsMap};
pub struct Prompt { pub struct Prompt {
template: liquid::Template, template: liquid::Template,
@ -93,7 +95,7 @@ impl Prompt {
&self, &self,
document: obkv::KvReaderU16<'_>, document: obkv::KvReaderU16<'_>,
side: DelAdd, side: DelAdd,
field_id_map: &FieldsIdsMap, field_id_map: &FieldsIdsMapWithMetadata,
) -> Result<String, RenderPromptError> { ) -> Result<String, RenderPromptError> {
let document = Document::new(document, side, field_id_map); let document = Document::new(document, side, field_id_map);
let context = Context::new(&document, field_id_map); let context = Context::new(&document, field_id_map);
@ -102,6 +104,40 @@ impl Prompt {
} }
} }
pub struct FieldsIdsMapWithMetadata<'a> {
fields_ids_map: &'a FieldsIdsMap,
metadata: BTreeMap<FieldId, FieldMetadata>,
}
impl<'a> FieldsIdsMapWithMetadata<'a> {
pub fn new(fields_ids_map: &'a FieldsIdsMap, searchable_fields_ids: &'_ [FieldId]) -> Self {
let mut metadata: BTreeMap<FieldId, FieldMetadata> =
fields_ids_map.ids().map(|id| (id, Default::default())).collect();
for searchable_field_id in searchable_fields_ids {
let Some(metadata) = metadata.get_mut(searchable_field_id) else { continue };
metadata.searchable = true;
}
Self { fields_ids_map, metadata }
}
pub fn metadata(&self, field_id: FieldId) -> Option<FieldMetadata> {
self.metadata.get(&field_id).copied()
}
}
impl<'a> Deref for FieldsIdsMapWithMetadata<'a> {
type Target = FieldsIdsMap;
fn deref(&self) -> &Self::Target {
self.fields_ids_map
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct FieldMetadata {
pub searchable: bool,
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::Prompt; use super::Prompt;