diff --git a/src/update/settings.rs b/src/update/settings.rs
index ad191ceec..f6528ed94 100644
--- a/src/update/settings.rs
+++ b/src/update/settings.rs
@@ -1,3 +1,5 @@
+use std::collections::HashMap;
+
use anyhow::Context;
use grenad::CompressionType;
use rayon::ThreadPool;
@@ -22,6 +24,7 @@ pub struct Settings<'a, 't, 'u, 'i> {
// however if it is `Some(None)` it means that the user forced a reset of the setting.
searchable_fields: Option>>,
displayed_fields: Option >>,
+ faceted_fields: Option>,
}
impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
@@ -39,6 +42,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
thread_pool: None,
searchable_fields: None,
displayed_fields: None,
+ faceted_fields: None,
}
}
@@ -58,13 +62,77 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
self.displayed_fields = Some(Some(names));
}
+ pub fn set_faceted_fields(&mut self, names: Vec) {
+ self.faceted_fields = Some(names);
+ }
+
pub fn execute(self, progress_callback: F) -> anyhow::Result<()>
where
F: Fn(UpdateIndexingStep) + Sync
{
+ if let Some(fields_names) = self.faceted_fields {
+ let current_faceted_fields = self.index.faceted_fields(self.wtxn)?;
+ let current_fields_ids_map = self.index.fields_ids_map(self.wtxn)?;
+
+ let mut fields_ids_map = current_fields_ids_map.clone();
+ let mut faceted_fields = HashMap::new();
+ for name in fields_names {
+ let id = fields_ids_map.insert(&name).context("field id limit reached")?;
+ match current_faceted_fields.get(&id) {
+ Some(ftype) => faceted_fields.insert(id, ftype.clone()),
+ None => faceted_fields.insert(id, None),
+ };
+ }
+
+ let transform = Transform {
+ rtxn: &self.wtxn,
+ index: self.index,
+ log_every_n: self.log_every_n,
+ chunk_compression_type: self.chunk_compression_type,
+ chunk_compression_level: self.chunk_compression_level,
+ chunk_fusing_shrink_size: self.chunk_fusing_shrink_size,
+ max_nb_chunks: self.max_nb_chunks,
+ max_memory: self.max_memory,
+ index_documents_method: IndexDocumentsMethod::ReplaceDocuments,
+ autogenerate_docids: false,
+ };
+
+ // We compute or generate the new primary key field id.
+ let primary_key = match self.index.primary_key(&self.wtxn)? {
+ Some(id) => {
+ let name = current_fields_ids_map.name(id).unwrap();
+ fields_ids_map.insert(name).context("field id limit reached")?
+ },
+ None => fields_ids_map.insert("id").context("field id limit reached")?,
+ };
+
+ // We remap the documents fields based on the new `FieldsIdsMap`.
+ let output = transform.remap_index_documents(primary_key, fields_ids_map.clone())?;
+
+ // We write the faceted_fields fields into the database here.
+ self.index.put_faceted_fields(self.wtxn, &faceted_fields)?;
+
+ // We clear the full database (words-fst, documents ids and documents content).
+ ClearDocuments::new(self.wtxn, self.index).execute()?;
+
+ // We index the generated `TransformOutput` which must contain
+ // all the documents with fields in the newly defined searchable order.
+ let mut indexing_builder = IndexDocuments::new(self.wtxn, self.index);
+ indexing_builder.log_every_n = self.log_every_n;
+ indexing_builder.max_nb_chunks = self.max_nb_chunks;
+ indexing_builder.max_memory = self.max_memory;
+ indexing_builder.linked_hash_map_size = self.linked_hash_map_size;
+ indexing_builder.chunk_compression_type = self.chunk_compression_type;
+ indexing_builder.chunk_compression_level = self.chunk_compression_level;
+ indexing_builder.chunk_fusing_shrink_size = self.chunk_fusing_shrink_size;
+ indexing_builder.thread_pool = self.thread_pool;
+ indexing_builder.execute_raw(output, &progress_callback)?;
+ }
+
// Check that the searchable attributes have been specified.
if let Some(value) = self.searchable_fields {
let current_displayed_fields = self.index.displayed_fields(self.wtxn)?;
+ let current_faceted_fields = self.index.faceted_fields(self.wtxn)?;
let current_fields_ids_map = self.index.fields_ids_map(self.wtxn)?;
let result = match value {
@@ -82,6 +150,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
fields_ids_map,
Some(searchable_fields),
current_displayed_fields.map(ToOwned::to_owned),
+ current_faceted_fields,
)
} else {
// We create or generate the fields ids corresponding to those names.
@@ -97,7 +166,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
fields_ids_map.insert(name).context("field id limit reached")?;
}
- // We must also update the displayed fields according to the new `FieldsIdsMap`.
+ // We must update the displayed fields according to the new `FieldsIdsMap`.
let displayed_fields = match current_displayed_fields {
Some(fields) => {
let mut displayed_fields = Vec::new();
@@ -111,17 +180,26 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
None => None,
};
- (fields_ids_map, Some(searchable_fields), displayed_fields)
+ // We must update the faceted fields according to the new `FieldsIdsMap`.
+ let mut faceted_fields = HashMap::new();
+ for (id, ftype) in current_faceted_fields {
+ let name = current_fields_ids_map.name(id).unwrap();
+ let id = fields_ids_map.id(name).context("field id limit reached")?;
+ faceted_fields.insert(id, ftype);
+ }
+
+ (fields_ids_map, Some(searchable_fields), displayed_fields, faceted_fields)
}
},
None => (
current_fields_ids_map.clone(),
None,
current_displayed_fields.map(ToOwned::to_owned),
+ current_faceted_fields,
),
};
- let (mut fields_ids_map, searchable_fields, displayed_fields) = result;
+ let (mut fields_ids_map, searchable_fields, displayed_fields, faceted_fields) = result;
let transform = Transform {
rtxn: &self.wtxn,
@@ -166,6 +244,9 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
None => self.index.delete_displayed_fields(self.wtxn).map(drop)?,
}
+ // We write the faceted_fields fields into the database here.
+ self.index.put_faceted_fields(self.wtxn, &faceted_fields)?;
+
// We clear the full database (words-fst, documents ids and documents content).
ClearDocuments::new(self.wtxn, self.index).execute()?;
@@ -180,7 +261,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
indexing_builder.chunk_compression_level = self.chunk_compression_level;
indexing_builder.chunk_fusing_shrink_size = self.chunk_fusing_shrink_size;
indexing_builder.thread_pool = self.thread_pool;
- indexing_builder.execute_raw(output, progress_callback)?;
+ indexing_builder.execute_raw(output, &progress_callback)?;
}
// Check that the displayed attributes have been specified.