mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-23 13:24:27 +01:00
Introduce the faceted fields setting
This commit is contained in:
parent
72f18759ba
commit
ebe7087bff
@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use grenad::CompressionType;
|
use grenad::CompressionType;
|
||||||
use rayon::ThreadPool;
|
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.
|
// however if it is `Some(None)` it means that the user forced a reset of the setting.
|
||||||
searchable_fields: Option<Option<Vec<String>>>,
|
searchable_fields: Option<Option<Vec<String>>>,
|
||||||
displayed_fields: Option<Option<Vec<String>>>,
|
displayed_fields: Option<Option<Vec<String>>>,
|
||||||
|
faceted_fields: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
|
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,
|
thread_pool: None,
|
||||||
searchable_fields: None,
|
searchable_fields: None,
|
||||||
displayed_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));
|
self.displayed_fields = Some(Some(names));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_faceted_fields(&mut self, names: Vec<String>) {
|
||||||
|
self.faceted_fields = Some(names);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn execute<F>(self, progress_callback: F) -> anyhow::Result<()>
|
pub fn execute<F>(self, progress_callback: F) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
F: Fn(UpdateIndexingStep) + Sync
|
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.
|
// Check that the searchable attributes have been specified.
|
||||||
if let Some(value) = self.searchable_fields {
|
if let Some(value) = self.searchable_fields {
|
||||||
let current_displayed_fields = self.index.displayed_fields(self.wtxn)?;
|
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 current_fields_ids_map = self.index.fields_ids_map(self.wtxn)?;
|
||||||
|
|
||||||
let result = match value {
|
let result = match value {
|
||||||
@ -82,6 +150,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
|
|||||||
fields_ids_map,
|
fields_ids_map,
|
||||||
Some(searchable_fields),
|
Some(searchable_fields),
|
||||||
current_displayed_fields.map(ToOwned::to_owned),
|
current_displayed_fields.map(ToOwned::to_owned),
|
||||||
|
current_faceted_fields,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// We create or generate the fields ids corresponding to those names.
|
// 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")?;
|
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 {
|
let displayed_fields = match current_displayed_fields {
|
||||||
Some(fields) => {
|
Some(fields) => {
|
||||||
let mut displayed_fields = Vec::new();
|
let mut displayed_fields = Vec::new();
|
||||||
@ -111,17 +180,26 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
|
|||||||
None => None,
|
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 => (
|
None => (
|
||||||
current_fields_ids_map.clone(),
|
current_fields_ids_map.clone(),
|
||||||
None,
|
None,
|
||||||
current_displayed_fields.map(ToOwned::to_owned),
|
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 {
|
let transform = Transform {
|
||||||
rtxn: &self.wtxn,
|
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)?,
|
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).
|
// We clear the full database (words-fst, documents ids and documents content).
|
||||||
ClearDocuments::new(self.wtxn, self.index).execute()?;
|
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_compression_level = self.chunk_compression_level;
|
||||||
indexing_builder.chunk_fusing_shrink_size = self.chunk_fusing_shrink_size;
|
indexing_builder.chunk_fusing_shrink_size = self.chunk_fusing_shrink_size;
|
||||||
indexing_builder.thread_pool = self.thread_pool;
|
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.
|
// Check that the displayed attributes have been specified.
|
||||||
|
Loading…
Reference in New Issue
Block a user