diff --git a/meilisearch-core/src/update/documents_addition.rs b/meilisearch-core/src/update/documents_addition.rs index ec45b40ad..5c14000b8 100644 --- a/meilisearch-core/src/update/documents_addition.rs +++ b/meilisearch-core/src/update/documents_addition.rs @@ -1,8 +1,9 @@ -use std::collections::HashMap; +use std::collections::{HashMap, BTreeSet}; use fst::{set::OpBuilder, SetBuilder}; use sdset::{duo::Union, SetOperation}; use serde::{Deserialize, Serialize}; +use meilisearch_schema::{Schema, DISPLAYED, INDEXED}; use crate::database::{MainT, UpdateT}; use crate::database::{UpdateEvent, UpdateEventsEmitter}; @@ -114,6 +115,11 @@ pub fn apply_documents_addition<'a, 'b>( None => return Err(Error::SchemaMissing), }; + if let Some(new_schema) = lazy_new_schema(&schema, &addition) { + main_store.put_schema(writer, &new_schema)?; + schema = new_schema; + } + let identifier = schema.identifier_name(); // 1. store documents ids for future deletion @@ -178,11 +184,16 @@ pub fn apply_documents_partial_addition<'a, 'b>( ) -> MResult<()> { let mut documents_additions = HashMap::new(); - let schema = match index.main.schema(writer)? { + Some(schema) => schema, None => return Err(Error::SchemaMissing), }; + if let Some(new_schema) = lazy_new_schema(&schema, &addition) { + main_store.put_schema(writer, &new_schema)?; + schema = new_schema; + } + let identifier = schema.identifier_name(); // 1. store documents ids for future deletion @@ -382,3 +393,30 @@ pub fn write_documents_addition_index( Ok(()) } + +pub fn lazy_new_schema( + schema: &Schema, + documents: &[HashMap], +) -> Option { + let mut attributes_to_add = BTreeSet::new(); + + for document in documents { + for (key, _) in document { + if schema.attribute(key).is_none() { + attributes_to_add.insert(key); + } + } + } + + if attributes_to_add.is_empty() { + return None + } + + let mut schema_builder = schema.to_builder(); + for attribute in attributes_to_add { + schema_builder.new_attribute(attribute, DISPLAYED | INDEXED); + } + let schema = schema_builder.build(); + + Some(schema) +} diff --git a/meilisearch-schema/src/lib.rs b/meilisearch-schema/src/lib.rs index 929316d41..a7125e434 100644 --- a/meilisearch-schema/src/lib.rs +++ b/meilisearch-schema/src/lib.rs @@ -145,7 +145,7 @@ struct InnerSchema { } impl Schema { - fn to_builder(&self) -> SchemaBuilder { + pub fn to_builder(&self) -> SchemaBuilder { let identifier = self.inner.identifier.clone(); let attributes = self.attributes_ordered(); SchemaBuilder {