Introduce the Settings update operation

This commit is contained in:
Clément Renault 2020-11-02 15:31:20 +01:00
parent 0c612f08c7
commit 995d72b8c1
No known key found for this signature in database
GPG Key ID: 92ADA4E935E71FA4
4 changed files with 142 additions and 3 deletions

View File

@ -160,6 +160,7 @@ enum UpdateStatus<M, P, N> {
enum UpdateMeta {
DocumentsAddition { method: String, format: String },
ClearDocuments,
Settings,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -268,6 +269,9 @@ pub fn run(opt: Opt) -> anyhow::Result<()> {
Ok(_count) => wtxn.commit().map_err(Into::into),
Err(e) => Err(e.into())
}
},
UpdateMeta::Settings => {
todo!()
}
};

View File

@ -2,6 +2,7 @@ mod available_documents_ids;
mod clear_documents;
mod delete_documents;
mod index_documents;
mod settings;
mod update_builder;
mod update_store;
@ -9,5 +10,6 @@ pub use self::available_documents_ids::AvailableDocumentsIds;
pub use self::clear_documents::ClearDocuments;
pub use self::delete_documents::DeleteDocuments;
pub use self::index_documents::{IndexDocuments, IndexDocumentsMethod, UpdateFormat};
pub use self::settings::Settings;
pub use self::update_builder::UpdateBuilder;
pub use self::update_store::UpdateStore;

126
src/update/settings.rs Normal file
View File

@ -0,0 +1,126 @@
use anyhow::Context;
use crate::Index;
pub struct Settings<'t, 'u, 'i> {
wtxn: &'t mut heed::RwTxn<'i, 'u>,
index: &'i Index,
// If the field is set to `None` it means that it hasn't been set by the user,
// however if it is `Some(None)` it means that the user forced a reset of the setting.
displayed_fields: Option<Option<Vec<String>>>,
}
impl<'t, 'u, 'i> Settings<'t, 'u, 'i> {
pub fn new(wtxn: &'t mut heed::RwTxn<'i, 'u>, index: &'i Index) -> Settings<'t, 'u, 'i> {
Settings { wtxn, index, displayed_fields: None }
}
pub fn reset_displayed_fields(&mut self) {
self.displayed_fields = Some(None);
}
pub fn set_displayed_fields(&mut self, names: Vec<String>) {
self.displayed_fields = Some(Some(names));
}
pub fn execute(self) -> anyhow::Result<()> {
// Check that the displayed attributes parameters has been specified.
if let Some(value) = self.displayed_fields {
match value {
// If it has been set, and it was a list of fields names, we create
// or generate the fields ids corresponds to those names and store them
// in the database in the order they were specified.
Some(fields_names) => {
let mut fields_ids_map = self.index.fields_ids_map(self.wtxn)?;
// We create or generate the fields ids corresponding to those names.
let mut fields_ids = Vec::new();
for name in fields_names {
let id = fields_ids_map.insert(&name).context("field id limit reached")?;
fields_ids.push(id);
}
self.index.put_displayed_fields(self.wtxn, &fields_ids)?;
},
// If it was set to `null` it means that the user wants to get the default behavior
// which is displaying all the attributes in no specific order (FieldsIdsMap order),
// we just have to delete the displayed fields.
None => {
self.index.delete_displayed_fields(self.wtxn)?;
},
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::update::{IndexDocuments, UpdateFormat};
use heed::EnvOpenOptions;
#[test]
fn default_displayed_fields() {
let path = tempfile::tempdir().unwrap();
let mut options = EnvOpenOptions::new();
options.map_size(10 * 1024 * 1024); // 10 MB
let index = Index::new(options, &path).unwrap();
// First we send 3 documents with ids from 1 to 3.
let mut wtxn = index.write_txn().unwrap();
let content = &b"name,age\nkevin,23\nkevina,21\nbenoit,34\n"[..];
let mut builder = IndexDocuments::new(&mut wtxn, &index);
builder.update_format(UpdateFormat::Csv);
builder.execute(content, |_, _| ()).unwrap();
wtxn.commit().unwrap();
// Check that the displayed fields are correctly set to `None` (default value).
let rtxn = index.read_txn().unwrap();
let fields_ids = index.displayed_fields(&rtxn).unwrap();
assert_eq!(fields_ids, None);
drop(rtxn);
}
#[test]
fn set_and_reset_displayed_field() {
let path = tempfile::tempdir().unwrap();
let mut options = EnvOpenOptions::new();
options.map_size(10 * 1024 * 1024); // 10 MB
let index = Index::new(options, &path).unwrap();
// First we send 3 documents with ids from 1 to 3.
let mut wtxn = index.write_txn().unwrap();
let content = &b"name,age\nkevin,23\nkevina,21\nbenoit,34\n"[..];
let mut builder = IndexDocuments::new(&mut wtxn, &index);
builder.update_format(UpdateFormat::Csv);
builder.execute(content, |_, _| ()).unwrap();
// In the same transaction we change the displayed fields to be only the age.
let mut builder = Settings::new(&mut wtxn, &index);
builder.set_displayed_fields(vec!["age".into()]);
builder.execute().unwrap();
wtxn.commit().unwrap();
// Check that the displayed fields are correctly set to only the "age" field.
let rtxn = index.read_txn().unwrap();
let fields_ids_map = index.fields_ids_map(&rtxn).unwrap();
let age_field_id = fields_ids_map.id("age").unwrap();
let fields_ids = index.displayed_fields(&rtxn).unwrap();
assert_eq!(fields_ids.unwrap(), &[age_field_id][..]);
drop(rtxn);
// We reset the fields ids to become `None`, the default value.
let mut wtxn = index.write_txn().unwrap();
let mut builder = Settings::new(&mut wtxn, &index);
builder.reset_displayed_fields();
builder.execute().unwrap();
wtxn.commit().unwrap();
// Check that the displayed fields are correctly set to `None` (default value).
let rtxn = index.read_txn().unwrap();
let fields_ids = index.displayed_fields(&rtxn).unwrap();
assert_eq!(fields_ids, None);
drop(rtxn);
}
}

View File

@ -1,9 +1,7 @@
use grenad::CompressionType;
use crate::Index;
use super::clear_documents::ClearDocuments;
use super::delete_documents::DeleteDocuments;
use super::index_documents::IndexDocuments;
use super::{ClearDocuments, DeleteDocuments, IndexDocuments, Settings};
pub struct UpdateBuilder {
pub(crate) log_every_n: Option<usize>,
@ -99,4 +97,13 @@ impl UpdateBuilder {
builder
}
pub fn settings<'t, 'u, 'i>(
self,
wtxn: &'t mut heed::RwTxn<'i, 'u>,
index: &'i Index,
) -> Settings<'t, 'u, 'i>
{
Settings::new(wtxn, index)
}
}