mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-26 23:04:26 +01:00
Merge #600
600: Simplify some unit tests r=ManyTheFish a=loiclec # Pull Request ## What does this PR do? Simplify the code that is used in unit tests to create and modify an index. Basically, the following code: ```rust 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(); let mut wtxn = index.write_txn().unwrap(); let content = documents!([ { "id": 0, "name": "kevin" }, ]); let config = IndexerConfig::default(); let indexing_config = IndexDocumentsConfig::default(); let builder = IndexDocuments::new(&mut wtxn, &index, &config, indexing_config, |_| ()).unwrap(); let (builder, user_error) = builder.add_documents(content).unwrap(); user_error.unwrap(); builder.execute().unwrap(); wtxn.commit.unwrap(); let mut wtxn = index.write_txn().unwrap(); let config = IndexerConfig::default(); let mut builder = Settings::new(&mut wtxn, &index, &config); builder.set_primary_key(S("docid")); builder.set_filterable_fields(hashset! { S("label") }); builder.execute(|_| ()).unwrap(); wtxn.commit().unwrap(); ``` becomes: ```rust let index = TempIndex::new(): index.add_documents(documents!( { "id": 0, "name": "kevin" }, )).unwrap(); index.update_settings(|settings| { settings.set_primary_key(S("docid")); settings.set_filterable_fields(hashset! { S("label") }); }).unwrap(); ``` Then there is a bunch of options to modify the indexing configs, the map size, to reuse a transaction, etc. For example: ```rust let mut index = TempIndex::new_with_map_size(1000 * 4096 * 10); index.index_documents_config.autogenerate_docids = true; let mut wtxn = index.write_txn().unwrap(); index.update_settings_using_wtxn(&mut wtxn, |settings| { settings.set_primary_key(S("docids")); }).unwrap(); wtxn.commit().unwrap(); ``` Co-authored-by: Loïc Lecrenier <loic@meilisearch.com> Co-authored-by: Loïc Lecrenier <loic.lecrenier@me.com> Co-authored-by: bors[bot] <26634292+bors[bot]@users.noreply.github.com>
This commit is contained in:
commit
950d8e4c44
@ -179,6 +179,17 @@ macro_rules! documents {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn documents_batch_reader_from_objects(
|
||||||
|
objects: impl IntoIterator<Item = Object>,
|
||||||
|
) -> DocumentsBatchReader<std::io::Cursor<Vec<u8>>> {
|
||||||
|
let mut builder = DocumentsBatchBuilder::new(Vec::new());
|
||||||
|
for object in objects {
|
||||||
|
builder.append_json_object(&object).unwrap();
|
||||||
|
}
|
||||||
|
DocumentsBatchReader::from_reader(std::io::Cursor::new(builder.into_inner().unwrap())).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
@ -1182,16 +1182,19 @@ pub(crate) mod tests {
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use big_s::S;
|
use big_s::S;
|
||||||
use heed::EnvOpenOptions;
|
use heed::{EnvOpenOptions, RwTxn};
|
||||||
use maplit::btreemap;
|
use maplit::btreemap;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
use crate::documents::DocumentsBatchReader;
|
||||||
use crate::index::{DEFAULT_MIN_WORD_LEN_ONE_TYPO, DEFAULT_MIN_WORD_LEN_TWO_TYPOS};
|
use crate::index::{DEFAULT_MIN_WORD_LEN_ONE_TYPO, DEFAULT_MIN_WORD_LEN_TWO_TYPOS};
|
||||||
use crate::update::{self, IndexDocuments, IndexDocumentsConfig, IndexerConfig};
|
use crate::update::{self, IndexDocuments, IndexDocumentsConfig, IndexerConfig, Settings};
|
||||||
use crate::Index;
|
use crate::Index;
|
||||||
|
|
||||||
pub(crate) struct TempIndex {
|
pub(crate) struct TempIndex {
|
||||||
inner: Index,
|
pub inner: Index,
|
||||||
|
pub indexer_config: IndexerConfig,
|
||||||
|
pub index_documents_config: IndexDocumentsConfig,
|
||||||
_tempdir: TempDir,
|
_tempdir: TempDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1204,43 +1207,88 @@ pub(crate) mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TempIndex {
|
impl TempIndex {
|
||||||
/// Creates a temporary index, with a default `4096 * 100` size. This should be enough for
|
/// Creates a temporary index
|
||||||
/// most tests.
|
pub fn new_with_map_size(size: usize) -> Self {
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut options = EnvOpenOptions::new();
|
let mut options = EnvOpenOptions::new();
|
||||||
options.map_size(100 * 4096);
|
options.map_size(size);
|
||||||
let _tempdir = TempDir::new_in(".").unwrap();
|
let _tempdir = TempDir::new_in(".").unwrap();
|
||||||
let inner = Index::new(options, _tempdir.path()).unwrap();
|
let inner = Index::new(options, _tempdir.path()).unwrap();
|
||||||
Self { inner, _tempdir }
|
let indexer_config = IndexerConfig::default();
|
||||||
|
let index_documents_config = IndexDocumentsConfig::default();
|
||||||
|
Self { inner, indexer_config, index_documents_config, _tempdir }
|
||||||
|
}
|
||||||
|
/// Creates a temporary index, with a default `4096 * 1000` size. This should be enough for
|
||||||
|
/// most tests.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::new_with_map_size(4096 * 1000)
|
||||||
|
}
|
||||||
|
pub fn add_documents_using_wtxn<'t, R>(
|
||||||
|
&'t self,
|
||||||
|
wtxn: &mut RwTxn<'t, '_>,
|
||||||
|
documents: DocumentsBatchReader<R>,
|
||||||
|
) -> Result<(), crate::error::Error>
|
||||||
|
where
|
||||||
|
R: std::io::Read + std::io::Seek,
|
||||||
|
{
|
||||||
|
let builder = IndexDocuments::new(
|
||||||
|
wtxn,
|
||||||
|
&self,
|
||||||
|
&self.indexer_config,
|
||||||
|
self.index_documents_config.clone(),
|
||||||
|
|_| (),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let (builder, user_error) = builder.add_documents(documents).unwrap();
|
||||||
|
user_error?;
|
||||||
|
builder.execute()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn add_documents<R>(
|
||||||
|
&self,
|
||||||
|
documents: DocumentsBatchReader<R>,
|
||||||
|
) -> Result<(), crate::error::Error>
|
||||||
|
where
|
||||||
|
R: std::io::Read + std::io::Seek,
|
||||||
|
{
|
||||||
|
let mut wtxn = self.write_txn().unwrap();
|
||||||
|
self.add_documents_using_wtxn(&mut wtxn, documents)?;
|
||||||
|
wtxn.commit().unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_settings(
|
||||||
|
&self,
|
||||||
|
update: impl Fn(&mut Settings),
|
||||||
|
) -> Result<(), crate::error::Error> {
|
||||||
|
let mut wtxn = self.write_txn().unwrap();
|
||||||
|
self.update_settings_using_wtxn(&mut wtxn, update)?;
|
||||||
|
wtxn.commit().unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn update_settings_using_wtxn<'t>(
|
||||||
|
&'t self,
|
||||||
|
wtxn: &mut RwTxn<'t, '_>,
|
||||||
|
update: impl Fn(&mut Settings),
|
||||||
|
) -> Result<(), crate::error::Error> {
|
||||||
|
let mut builder = update::Settings::new(wtxn, &self.inner, &self.indexer_config);
|
||||||
|
update(&mut builder);
|
||||||
|
builder.execute(drop)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn initial_field_distribution() {
|
fn initial_field_distribution() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
.add_documents(documents!([
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
|
||||||
let content = documents!([
|
|
||||||
{ "id": 1, "name": "kevin" },
|
{ "id": 1, "name": "kevin" },
|
||||||
{ "id": 2, "name": "bob", "age": 20 },
|
{ "id": 2, "name": "bob", "age": 20 },
|
||||||
{ "id": 2, "name": "bob", "age": 20 },
|
{ "id": 2, "name": "bob", "age": 20 },
|
||||||
]);
|
]))
|
||||||
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let field_distribution = index.field_distribution(&rtxn).unwrap();
|
let field_distribution = index.field_distribution(&rtxn).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
field_distribution,
|
field_distribution,
|
||||||
@ -1253,19 +1301,13 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
// we add all the documents a second time. we are supposed to get the same
|
// we add all the documents a second time. we are supposed to get the same
|
||||||
// field_distribution in the end
|
// field_distribution in the end
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let builder =
|
.add_documents(documents!([
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
|
||||||
let content = documents!([
|
|
||||||
{ "id": 1, "name": "kevin" },
|
{ "id": 1, "name": "kevin" },
|
||||||
{ "id": 2, "name": "bob", "age": 20 },
|
{ "id": 2, "name": "bob", "age": 20 },
|
||||||
{ "id": 2, "name": "bob", "age": 20 },
|
{ "id": 2, "name": "bob", "age": 20 },
|
||||||
]);
|
]))
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
.unwrap();
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
@ -1280,19 +1322,12 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// then we update a document by removing one field and another by adding one field
|
// then we update a document by removing one field and another by adding one field
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents(documents!([
|
||||||
{ "id": 1, "name": "kevin", "has_dog": true },
|
{ "id": 1, "name": "kevin", "has_dog": true },
|
||||||
{ "id": 2, "name": "bob" }
|
{ "id": 2, "name": "bob" }
|
||||||
]);
|
]))
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
@ -1341,35 +1376,19 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_documents_and_set_searchable_fields() {
|
fn add_documents_and_set_searchable_fields() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
.add_documents(documents!([
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
|
||||||
let content = documents!([
|
|
||||||
{ "id": 1, "doggo": "kevin" },
|
{ "id": 1, "doggo": "kevin" },
|
||||||
{ "id": 2, "doggo": { "name": "bob", "age": 20 } },
|
{ "id": 2, "doggo": { "name": "bob", "age": 20 } },
|
||||||
{ "id": 3, "name": "jean", "age": 25 },
|
{ "id": 3, "name": "jean", "age": 25 },
|
||||||
]);
|
]))
|
||||||
|
.unwrap();
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
.update_settings(|settings| {
|
||||||
let builder =
|
settings.set_searchable_fields(vec![S("doggo"), S("name")]);
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// set searchable fields
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
|
||||||
let mut builder = update::Settings::new(&mut wtxn, &index, &config);
|
|
||||||
builder.set_searchable_fields(vec![S("doggo"), S("name")]);
|
|
||||||
|
|
||||||
builder.execute(drop).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// ensure we get the right real searchable fields + user defined searchable fields
|
// ensure we get the right real searchable fields + user defined searchable fields
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1383,19 +1402,13 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_searchable_fields_and_add_documents() {
|
fn set_searchable_fields_and_add_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// set searchable fields
|
index
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
.update_settings(|settings| {
|
||||||
let mut builder = update::Settings::new(&mut wtxn, &index, &config);
|
settings.set_searchable_fields(vec![S("doggo"), S("name")]);
|
||||||
builder.set_searchable_fields(vec![S("doggo"), S("name")]);
|
})
|
||||||
|
.unwrap();
|
||||||
builder.execute(drop).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// ensure we get the right real searchable fields + user defined searchable fields
|
// ensure we get the right real searchable fields + user defined searchable fields
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1405,21 +1418,13 @@ pub(crate) mod tests {
|
|||||||
let user_defined = index.user_defined_searchable_fields(&rtxn).unwrap().unwrap();
|
let user_defined = index.user_defined_searchable_fields(&rtxn).unwrap().unwrap();
|
||||||
assert_eq!(user_defined, &["doggo", "name"]);
|
assert_eq!(user_defined, &["doggo", "name"]);
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let content = documents!([
|
.add_documents(documents!([
|
||||||
{ "id": 1, "doggo": "kevin" },
|
{ "id": 1, "doggo": "kevin" },
|
||||||
{ "id": 2, "doggo": { "name": "bob", "age": 20 } },
|
{ "id": 2, "doggo": { "name": "bob", "age": 20 } },
|
||||||
{ "id": 3, "name": "jean", "age": 25 },
|
{ "id": 3, "name": "jean", "age": 25 },
|
||||||
]);
|
]))
|
||||||
|
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// ensure we get the right real searchable fields + user defined searchable fields
|
// ensure we get the right real searchable fields + user defined searchable fields
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
@ -494,28 +494,21 @@ mod tests {
|
|||||||
|
|
||||||
use big_s::S;
|
use big_s::S;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use heed::EnvOpenOptions;
|
|
||||||
use maplit::hashset;
|
use maplit::hashset;
|
||||||
|
|
||||||
use super::*;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::update::{self, IndexDocuments, IndexDocumentsConfig, IndexerConfig, Settings};
|
use crate::Filter;
|
||||||
use crate::Index;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_db() {
|
fn empty_db() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
// Set the filterable fields to be the channel.
|
// Set the filterable fields to be the channel.
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
.update_settings(|settings| {
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
settings.set_searchable_fields(vec![S("PrIcE")]); // to keep the fields order
|
||||||
builder.set_searchable_fields(vec![S("PrIcE")]); // to keep the fields order
|
settings.set_filterable_fields(hashset! { S("PrIcE") });
|
||||||
builder.set_filterable_fields(hashset! { S("PrIcE") });
|
})
|
||||||
builder.execute(|_| ()).unwrap();
|
.unwrap();
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
@ -592,10 +585,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_filterable() {
|
fn not_filterable() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let filter = Filter::from_str("_geoRadius(42, 150, 10)").unwrap().unwrap();
|
let filter = Filter::from_str("_geoRadius(42, 150, 10)").unwrap().unwrap();
|
||||||
@ -611,14 +601,12 @@ mod tests {
|
|||||||
));
|
));
|
||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
// Set the filterable fields to be the channel.
|
.update_settings(|settings| {
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
settings.set_searchable_fields(vec![S("title")]);
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
settings.set_filterable_fields(hashset! { S("title") });
|
||||||
builder.set_searchable_fields(vec![S("title")]);
|
})
|
||||||
builder.set_filterable_fields(hashset! { S("title") });
|
.unwrap();
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
@ -637,13 +625,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn escaped_quote_in_filter_value_2380() {
|
fn escaped_quote_in_filter_value_2380() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let content = documents!([
|
.add_documents(documents!([
|
||||||
{
|
{
|
||||||
"id": "test_1",
|
"id": "test_1",
|
||||||
"monitor_diagonal": "27' to 30'"
|
"monitor_diagonal": "27' to 30'"
|
||||||
@ -656,73 +641,48 @@ mod tests {
|
|||||||
"id": "test_3",
|
"id": "test_3",
|
||||||
"monitor_diagonal": "27\" to 30'"
|
"monitor_diagonal": "27\" to 30'"
|
||||||
},
|
},
|
||||||
]);
|
]))
|
||||||
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
wtxn.commit().unwrap();
|
index
|
||||||
|
.update_settings(|settings| {
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
settings.set_filterable_fields(hashset!(S("monitor_diagonal")));
|
||||||
let mut builder = update::Settings::new(&mut wtxn, &index, &config);
|
})
|
||||||
|
.unwrap();
|
||||||
builder.set_filterable_fields(hashset!(S("monitor_diagonal")));
|
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = crate::Search::new(&rtxn, &index);
|
||||||
// this filter is copy pasted from #2380 with the exact same espace sequence
|
// this filter is copy pasted from #2380 with the exact same espace sequence
|
||||||
search.filter(
|
search.filter(Filter::from_str("monitor_diagonal = '27\" to 30\\''").unwrap().unwrap());
|
||||||
crate::Filter::from_str("monitor_diagonal = '27\" to 30\\''").unwrap().unwrap(),
|
|
||||||
);
|
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
assert_eq!(documents_ids, vec![2]);
|
assert_eq!(documents_ids, vec![2]);
|
||||||
|
|
||||||
search.filter(
|
search.filter(Filter::from_str(r#"monitor_diagonal = "27' to 30'" "#).unwrap().unwrap());
|
||||||
crate::Filter::from_str(r#"monitor_diagonal = "27' to 30'" "#).unwrap().unwrap(),
|
|
||||||
);
|
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
assert_eq!(documents_ids, vec![0]);
|
assert_eq!(documents_ids, vec![0]);
|
||||||
|
|
||||||
search.filter(
|
search.filter(Filter::from_str(r#"monitor_diagonal = "27\" to 30\"" "#).unwrap().unwrap());
|
||||||
crate::Filter::from_str(r#"monitor_diagonal = "27\" to 30\"" "#).unwrap().unwrap(),
|
|
||||||
);
|
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
assert_eq!(documents_ids, vec![1]);
|
assert_eq!(documents_ids, vec![1]);
|
||||||
|
|
||||||
search.filter(
|
search.filter(Filter::from_str(r#"monitor_diagonal = "27\" to 30'" "#).unwrap().unwrap());
|
||||||
crate::Filter::from_str(r#"monitor_diagonal = "27\" to 30'" "#).unwrap().unwrap(),
|
|
||||||
);
|
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
assert_eq!(documents_ids, vec![2]);
|
assert_eq!(documents_ids, vec![2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn geo_radius_error() {
|
fn geo_radius_error() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
// Set the filterable fields to be the channel.
|
.update_settings(|settings| {
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
settings.set_searchable_fields(vec![S("_geo"), S("price")]); // to keep the fields order
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
settings.set_filterable_fields(hashset! { S("_geo"), S("price") });
|
||||||
builder.set_searchable_fields(vec![S("_geo"), S("price")]); // to keep the fields order
|
})
|
||||||
builder.set_filterable_fields(hashset! { S("_geo"), S("price") });
|
.unwrap();
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
// georadius have a bad latitude
|
// georadius have a bad latitude
|
||||||
let filter = Filter::from_str("_geoRadius(-100, 150, 10)").unwrap().unwrap();
|
let filter = Filter::from_str("_geoRadius(-100, 150, 10)").unwrap().unwrap();
|
||||||
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
||||||
|
@ -82,36 +82,25 @@ impl<'t, 'u, 'i> ClearDocuments<'t, 'u, 'i> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use heed::EnvOpenOptions;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::update::{IndexDocuments, IndexDocumentsConfig, IndexerConfig};
|
use crate::index::tests::TempIndex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn clear_documents() {
|
fn clear_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(&mut wtxn, documents!([
|
||||||
{ "id": 0, "name": "kevin", "age": 20 },
|
{ "id": 0, "name": "kevin", "age": 20 },
|
||||||
{ "id": 1, "name": "kevina" },
|
{ "id": 1, "name": "kevina" },
|
||||||
{ "id": 2, "name": "benoit", "country": "France", "_geo": { "lng": 42, "lat": 35 } }
|
{ "id": 2, "name": "benoit", "country": "France", "_geo": { "lng": 42, "lat": 35 } }
|
||||||
]);
|
]))
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
.unwrap();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config, |_| ()).unwrap();
|
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// Clear all documents from the database.
|
// Clear all documents from the database.
|
||||||
let builder = ClearDocuments::new(&mut wtxn, &index);
|
let builder = ClearDocuments::new(&mut wtxn, &index);
|
||||||
assert_eq!(builder.execute().unwrap(), 3);
|
assert_eq!(builder.execute().unwrap(), 3);
|
||||||
|
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
@ -654,26 +654,13 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use big_s::S;
|
use big_s::S;
|
||||||
use heed::{EnvOpenOptions, RwTxn};
|
use heed::RwTxn;
|
||||||
use maplit::hashset;
|
use maplit::hashset;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::update::{IndexDocuments, IndexDocumentsConfig, IndexerConfig, Settings};
|
use crate::index::tests::TempIndex;
|
||||||
use crate::Filter;
|
use crate::Filter;
|
||||||
|
|
||||||
fn insert_documents<'t, R: std::io::Read + std::io::Seek>(
|
|
||||||
wtxn: &mut RwTxn<'t, '_>,
|
|
||||||
index: &'t Index,
|
|
||||||
documents: crate::documents::DocumentsBatchReader<R>,
|
|
||||||
) {
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder = IndexDocuments::new(wtxn, &index, &config, indexing_config, |_| ()).unwrap();
|
|
||||||
let (builder, user_error) = builder.add_documents(documents).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn delete_documents<'t>(
|
fn delete_documents<'t>(
|
||||||
wtxn: &mut RwTxn<'t, '_>,
|
wtxn: &mut RwTxn<'t, '_>,
|
||||||
index: &'t Index,
|
index: &'t Index,
|
||||||
@ -695,24 +682,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_documents_with_numbers_as_primary_key() {
|
fn delete_documents_with_numbers_as_primary_key() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "id": 0, "name": "kevin", "object": { "key1": "value1", "key2": "value2" } },
|
{ "id": 0, "name": "kevin", "object": { "key1": "value1", "key2": "value2" } },
|
||||||
{ "id": 1, "name": "kevina", "array": ["I", "am", "fine"] },
|
{ "id": 1, "name": "kevina", "array": ["I", "am", "fine"] },
|
||||||
{ "id": 2, "name": "benoit", "array_of_object": [{ "wow": "amazing" }] }
|
{ "id": 2, "name": "benoit", "array_of_object": [{ "wow": "amazing" }] }
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
.unwrap();
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config, |_| ()).unwrap();
|
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// delete those documents, ids are synchronous therefore 0, 1, and 2.
|
// delete those documents, ids are synchronous therefore 0, 1, and 2.
|
||||||
let mut builder = DeleteDocuments::new(&mut wtxn, &index).unwrap();
|
let mut builder = DeleteDocuments::new(&mut wtxn, &index).unwrap();
|
||||||
@ -730,25 +712,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_documents_with_strange_primary_key() {
|
fn delete_documents_with_strange_primary_key() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "mysuperid": 0, "name": "kevin" },
|
{ "mysuperid": 0, "name": "kevin" },
|
||||||
{ "mysuperid": 1, "name": "kevina" },
|
{ "mysuperid": 1, "name": "kevina" },
|
||||||
{ "mysuperid": 2, "name": "benoit" }
|
{ "mysuperid": 2, "name": "benoit" }
|
||||||
]);
|
]),
|
||||||
|
)
|
||||||
let config = IndexerConfig::default();
|
.unwrap();
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config, |_| ()).unwrap();
|
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// Delete not all of the documents but some of them.
|
// Delete not all of the documents but some of them.
|
||||||
let mut builder = DeleteDocuments::new(&mut wtxn, &index).unwrap();
|
let mut builder = DeleteDocuments::new(&mut wtxn, &index).unwrap();
|
||||||
@ -761,19 +737,21 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn filtered_placeholder_search_should_not_return_deleted_documents() {
|
fn filtered_placeholder_search_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
|
||||||
builder.set_primary_key(S("docid"));
|
|
||||||
builder.set_filterable_fields(hashset! { S("label") });
|
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
|
settings.set_primary_key(S("docid"));
|
||||||
|
settings.set_filterable_fields(hashset! { S("label") });
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "docid": "1_4", "label": "sign" },
|
{ "docid": "1_4", "label": "sign" },
|
||||||
{ "docid": "1_5", "label": "letter" },
|
{ "docid": "1_5", "label": "letter" },
|
||||||
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
||||||
@ -794,9 +772,10 @@ mod tests {
|
|||||||
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
||||||
{ "docid": "1_68", "label": "design" },
|
{ "docid": "1_68", "label": "design" },
|
||||||
{ "docid": "1_69", "label": "geometry" }
|
{ "docid": "1_69", "label": "geometry" }
|
||||||
]);
|
]),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
|
||||||
delete_documents(&mut wtxn, &index, &["1_4"]);
|
delete_documents(&mut wtxn, &index, &["1_4"]);
|
||||||
|
|
||||||
// Placeholder search with filter
|
// Placeholder search with filter
|
||||||
@ -809,18 +788,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn placeholder_search_should_not_return_deleted_documents() {
|
fn placeholder_search_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_primary_key(S("docid"));
|
settings.set_primary_key(S("docid"));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "docid": "1_4", "label": "sign" },
|
{ "docid": "1_4", "label": "sign" },
|
||||||
{ "docid": "1_5", "label": "letter" },
|
{ "docid": "1_5", "label": "letter" },
|
||||||
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
||||||
@ -841,9 +821,10 @@ mod tests {
|
|||||||
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
||||||
{ "docid": "1_68", "label": "design" },
|
{ "docid": "1_68", "label": "design" },
|
||||||
{ "docid": "1_69", "label": "geometry" }
|
{ "docid": "1_69", "label": "geometry" }
|
||||||
]);
|
]),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
|
||||||
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &["1_4"]);
|
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &["1_4"]);
|
||||||
|
|
||||||
// Placeholder search
|
// Placeholder search
|
||||||
@ -862,18 +843,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn search_should_not_return_deleted_documents() {
|
fn search_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_primary_key(S("docid"));
|
settings.set_primary_key(S("docid"));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{"docid": "1_4", "label": "sign"},
|
{"docid": "1_4", "label": "sign"},
|
||||||
{"docid": "1_5", "label": "letter"},
|
{"docid": "1_5", "label": "letter"},
|
||||||
{"docid": "1_7", "label": "abstract,cartoon,design,pattern"},
|
{"docid": "1_7", "label": "abstract,cartoon,design,pattern"},
|
||||||
@ -894,9 +876,10 @@ mod tests {
|
|||||||
{"docid": "1_58","label": "abstract,art,cartoon"},
|
{"docid": "1_58","label": "abstract,art,cartoon"},
|
||||||
{"docid": "1_68","label": "design"},
|
{"docid": "1_68","label": "design"},
|
||||||
{"docid": "1_69","label": "geometry"}
|
{"docid": "1_69","label": "geometry"}
|
||||||
]);
|
]),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
|
||||||
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &["1_7", "1_52"]);
|
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &["1_7", "1_52"]);
|
||||||
|
|
||||||
// search for abstract
|
// search for abstract
|
||||||
@ -915,20 +898,18 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn geo_filtered_placeholder_search_should_not_return_deleted_documents() {
|
fn geo_filtered_placeholder_search_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_primary_key(S("id"));
|
settings.set_primary_key(S("id"));
|
||||||
builder.set_filterable_fields(hashset!(S("_geo")));
|
settings.set_filterable_fields(hashset!(S("_geo")));
|
||||||
builder.set_sortable_fields(hashset!(S("_geo")));
|
settings.set_sortable_fields(hashset!(S("_geo")));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index.add_documents_using_wtxn(&mut wtxn, documents!([
|
||||||
{ "id": "1", "city": "Lille", "_geo": { "lat": 50.6299, "lng": 3.0569 } },
|
{ "id": "1", "city": "Lille", "_geo": { "lat": 50.6299, "lng": 3.0569 } },
|
||||||
{ "id": "2", "city": "Mons-en-Barœul", "_geo": { "lat": 50.6415, "lng": 3.1106 } },
|
{ "id": "2", "city": "Mons-en-Barœul", "_geo": { "lat": 50.6415, "lng": 3.1106 } },
|
||||||
{ "id": "3", "city": "Hellemmes", "_geo": { "lat": 50.6312, "lng": 3.1106 } },
|
{ "id": "3", "city": "Hellemmes", "_geo": { "lat": 50.6312, "lng": 3.1106 } },
|
||||||
@ -949,10 +930,9 @@ mod tests {
|
|||||||
{ "id": "18", "city": "Amiens", "_geo": { "lat": 49.9314, "lng": 2.2710 } },
|
{ "id": "18", "city": "Amiens", "_geo": { "lat": 49.9314, "lng": 2.2710 } },
|
||||||
{ "id": "19", "city": "Compiègne", "_geo": { "lat": 49.4449, "lng": 2.7913 } },
|
{ "id": "19", "city": "Compiègne", "_geo": { "lat": 49.4449, "lng": 2.7913 } },
|
||||||
{ "id": "20", "city": "Paris", "_geo": { "lat": 48.9021, "lng": 2.3708 } }
|
{ "id": "20", "city": "Paris", "_geo": { "lat": 48.9021, "lng": 2.3708 } }
|
||||||
]);
|
])).unwrap();
|
||||||
let external_ids_to_delete = ["5", "6", "7", "12", "17", "19"];
|
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
let external_ids_to_delete = ["5", "6", "7", "12", "17", "19"];
|
||||||
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &external_ids_to_delete);
|
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &external_ids_to_delete);
|
||||||
|
|
||||||
// Placeholder search with geo filter
|
// Placeholder search with geo filter
|
||||||
@ -972,18 +952,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_documents_should_not_return_deleted_documents() {
|
fn get_documents_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_primary_key(S("docid"));
|
settings.set_primary_key(S("docid"));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "docid": "1_4", "label": "sign" },
|
{ "docid": "1_4", "label": "sign" },
|
||||||
{ "docid": "1_5", "label": "letter" },
|
{ "docid": "1_5", "label": "letter" },
|
||||||
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern" },
|
||||||
@ -1004,9 +985,10 @@ mod tests {
|
|||||||
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
{ "docid": "1_58", "label": "abstract,art,cartoon" },
|
||||||
{ "docid": "1_68", "label": "design" },
|
{ "docid": "1_68", "label": "design" },
|
||||||
{ "docid": "1_69", "label": "geometry" }
|
{ "docid": "1_69", "label": "geometry" }
|
||||||
]);
|
]),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
|
||||||
let deleted_external_ids = ["1_7", "1_52"];
|
let deleted_external_ids = ["1_7", "1_52"];
|
||||||
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &deleted_external_ids);
|
let deleted_internal_ids = delete_documents(&mut wtxn, &index, &deleted_external_ids);
|
||||||
|
|
||||||
@ -1042,18 +1024,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stats_should_not_return_deleted_documents() {
|
fn stats_should_not_return_deleted_documents() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
|
||||||
builder.set_primary_key(S("docid"));
|
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
|
settings.set_primary_key(S("docid"));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
index.add_documents_using_wtxn(&mut wtxn, documents!([
|
||||||
{ "docid": "1_4", "label": "sign"},
|
{ "docid": "1_4", "label": "sign"},
|
||||||
{ "docid": "1_5", "label": "letter"},
|
{ "docid": "1_5", "label": "letter"},
|
||||||
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern", "title": "Mickey Mouse"},
|
{ "docid": "1_7", "label": "abstract,cartoon,design,pattern", "title": "Mickey Mouse"},
|
||||||
@ -1074,9 +1055,8 @@ mod tests {
|
|||||||
{ "docid": "1_58", "label": "abstract,art,cartoon"},
|
{ "docid": "1_58", "label": "abstract,art,cartoon"},
|
||||||
{ "docid": "1_68", "label": "design"},
|
{ "docid": "1_68", "label": "design"},
|
||||||
{ "docid": "1_69", "label": "geometry"}
|
{ "docid": "1_69", "label": "geometry"}
|
||||||
]);
|
])).unwrap();
|
||||||
|
|
||||||
insert_documents(&mut wtxn, &index, content);
|
|
||||||
delete_documents(&mut wtxn, &index, &["1_7", "1_52"]);
|
delete_documents(&mut wtxn, &index, &["1_7", "1_52"]);
|
||||||
|
|
||||||
// count internal documents
|
// count internal documents
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -709,45 +709,38 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use big_s::S;
|
use big_s::S;
|
||||||
use heed::types::ByteSlice;
|
use heed::types::ByteSlice;
|
||||||
use heed::EnvOpenOptions;
|
|
||||||
use maplit::{btreeset, hashmap, hashset};
|
use maplit::{btreeset, hashmap, hashset};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::update::IndexDocuments;
|
|
||||||
use crate::{Criterion, Filter, SearchResult};
|
use crate::{Criterion, Filter, SearchResult};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_and_reset_searchable_fields() {
|
fn set_and_reset_searchable_fields() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
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.
|
// First we send 3 documents with ids from 1 to 3.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "id": 1, "name": "kevin", "age": 23 },
|
{ "id": 1, "name": "kevin", "age": 23 },
|
||||||
{ "id": 2, "name": "kevina", "age": 21},
|
{ "id": 2, "name": "kevina", "age": 21},
|
||||||
{ "id": 3, "name": "benoit", "age": 34 }
|
{ "id": 3, "name": "benoit", "age": 34 }
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config = IndexDocumentsConfig::default();
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// We change the searchable fields to be the "name" field only.
|
// We change the searchable fields to be the "name" field only.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_searchable_fields(vec!["name".into()]);
|
settings.set_searchable_fields(vec!["name".into()]);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// Check that the searchable field is correctly set to "name" only.
|
// Check that the searchable field is correctly set to "name" only.
|
||||||
@ -766,11 +759,11 @@ mod tests {
|
|||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
// We change the searchable fields to be the "name" field only.
|
// We change the searchable fields to be the "name" field only.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.reset_searchable_fields();
|
settings.reset_searchable_fields();
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Check that the searchable field have been reset and documents are found now.
|
// Check that the searchable field have been reset and documents are found now.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -784,36 +777,30 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mixup_searchable_with_displayed_fields() {
|
fn mixup_searchable_with_displayed_fields() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
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 mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
// First we send 3 documents with ids from 1 to 3.
|
||||||
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// In the same transaction we change the displayed fields to be only the "age".
|
// In the same transaction we change the displayed fields to be only the "age".
|
||||||
// We also change the searchable fields to be the "name" field only.
|
// We also change the searchable fields to be the "name" field only.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.set_displayed_fields(vec!["age".into()]);
|
settings.set_displayed_fields(vec!["age".into()]);
|
||||||
builder.set_searchable_fields(vec!["name".into()]);
|
settings.set_searchable_fields(vec!["name".into()]);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// Check that the displayed fields are correctly set to `None` (default value).
|
// Check that the displayed fields are correctly set to `None` (default value).
|
||||||
@ -823,11 +810,11 @@ mod tests {
|
|||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
// We change the searchable fields to be the "name" field only.
|
// We change the searchable fields to be the "name" field only.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.reset_searchable_fields();
|
settings.reset_searchable_fields();
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Check that the displayed fields always contains only the "age" field.
|
// Check that the displayed fields always contains only the "age" field.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -837,28 +824,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_displayed_fields() {
|
fn default_displayed_fields() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
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.
|
// First we send 3 documents with ids from 1 to 3.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let content = documents!([
|
.add_documents(documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]))
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Check that the displayed fields are correctly set to `None` (default value).
|
// Check that the displayed fields are correctly set to `None` (default value).
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -868,32 +844,25 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_and_reset_displayed_field() {
|
fn set_and_reset_displayed_field() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
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 mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config =
|
.unwrap();
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
index
|
||||||
let builder =
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
settings.set_displayed_fields(vec!["age".into()]);
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// In the same transaction we change the displayed fields to be only the age.
|
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
|
||||||
builder.set_displayed_fields(vec!["age".into()]);
|
|
||||||
builder.execute(|_| ()).unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// Check that the displayed fields are correctly set to only the "age" field.
|
// Check that the displayed fields are correctly set to only the "age" field.
|
||||||
@ -903,11 +872,11 @@ mod tests {
|
|||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
// We reset the fields ids to become `None`, the default value.
|
// We reset the fields ids to become `None`, the default value.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.reset_displayed_fields();
|
settings.reset_displayed_fields();
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Check that the displayed fields are correctly set to `None` (default value).
|
// Check that the displayed fields are correctly set to `None` (default value).
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -917,34 +886,24 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_filterable_fields() {
|
fn set_filterable_fields() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the filterable fields to be the age.
|
// Set the filterable fields to be the age.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_filterable_fields(hashset! { S("age") });
|
settings.set_filterable_fields(hashset! { S("age") });
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Then index some documents.
|
// Then index some documents.
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents(documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]))
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Check that the displayed fields are correctly set.
|
// Check that the displayed fields are correctly set.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -970,22 +929,13 @@ mod tests {
|
|||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
// Index a little more documents with new and current facets values.
|
// Index a little more documents with new and current facets values.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let content = documents!([
|
.add_documents(documents!([
|
||||||
{ "name": "kevin2", "age": 23},
|
{ "name": "kevin2", "age": 23},
|
||||||
{ "name": "kevina2", "age": 21 },
|
{ "name": "kevina2", "age": 21 },
|
||||||
{ "name": "benoit", "age": 35 }
|
{ "name": "benoit", "age": 35 }
|
||||||
]);
|
]))
|
||||||
|
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
// Only count the field_id 0 and level 0 facet values.
|
// Only count the field_id 0 and level 0 facet values.
|
||||||
@ -1000,35 +950,25 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_asc_desc_field() {
|
fn set_asc_desc_field() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the filterable fields to be the age.
|
// Set the filterable fields to be the age.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
// Don't display the generated `id` field.
|
settings.set_displayed_fields(vec![S("name")]);
|
||||||
builder.set_displayed_fields(vec![S("name")]);
|
settings.set_criteria(vec![S("age:asc")]);
|
||||||
builder.set_criteria(vec![S("age:asc")]);
|
})
|
||||||
builder.execute(|_| ()).unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Then index some documents.
|
// Then index some documents.
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents(documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]))
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Run an empty query just to ensure that the search results are ordered.
|
// Run an empty query just to ensure that the search results are ordered.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1048,22 +988,21 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_distinct_field() {
|
fn set_distinct_field() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the filterable fields to be the age.
|
// Set the filterable fields to be the age.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
// Don't display the generated `id` field.
|
// Don't display the generated `id` field.
|
||||||
builder.set_displayed_fields(vec![S("name"), S("age")]);
|
settings.set_displayed_fields(vec![S("name"), S("age")]);
|
||||||
builder.set_distinct_field(S("age"));
|
settings.set_distinct_field(S("age"));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Then index some documents.
|
// Then index some documents.
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents(documents!([
|
||||||
{ "name": "kevin", "age": 23 },
|
{ "name": "kevin", "age": 23 },
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 },
|
{ "name": "benoit", "age": 34 },
|
||||||
@ -1071,16 +1010,8 @@ mod tests {
|
|||||||
{ "name": "bertrand", "age": 34 },
|
{ "name": "bertrand", "age": 34 },
|
||||||
{ "name": "bernie", "age": 34 },
|
{ "name": "bernie", "age": 34 },
|
||||||
{ "name": "ben", "age": 34 }
|
{ "name": "ben", "age": 34 }
|
||||||
]);
|
]))
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Run an empty query just to ensure that the search results are ordered.
|
// Run an empty query just to ensure that the search results are ordered.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1092,22 +1023,21 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_nested_distinct_field() {
|
fn set_nested_distinct_field() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the filterable fields to be the age.
|
// Set the filterable fields to be the age.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
// Don't display the generated `id` field.
|
// Don't display the generated `id` field.
|
||||||
builder.set_displayed_fields(vec![S("person")]);
|
settings.set_displayed_fields(vec![S("person")]);
|
||||||
builder.set_distinct_field(S("person.age"));
|
settings.set_distinct_field(S("person.age"));
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Then index some documents.
|
// Then index some documents.
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents(documents!([
|
||||||
{ "person": { "name": "kevin", "age": 23 }},
|
{ "person": { "name": "kevin", "age": 23 }},
|
||||||
{ "person": { "name": "kevina", "age": 21 }},
|
{ "person": { "name": "kevina", "age": 21 }},
|
||||||
{ "person": { "name": "benoit", "age": 34 }},
|
{ "person": { "name": "benoit", "age": 34 }},
|
||||||
@ -1115,16 +1045,8 @@ mod tests {
|
|||||||
{ "person": { "name": "bertrand", "age": 34 }},
|
{ "person": { "name": "bertrand", "age": 34 }},
|
||||||
{ "person": { "name": "bernie", "age": 34 }},
|
{ "person": { "name": "bernie", "age": 34 }},
|
||||||
{ "person": { "name": "ben", "age": 34 }}
|
{ "person": { "name": "ben", "age": 34 }}
|
||||||
]);
|
]))
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Run an empty query just to ensure that the search results are ordered.
|
// Run an empty query just to ensure that the search results are ordered.
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1136,28 +1058,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_stop_words() {
|
fn default_stop_words() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
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.
|
// First we send 3 documents with ids from 1 to 3.
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let content = documents!([
|
.add_documents(documents!([
|
||||||
{ "name": "kevin", "age": 23},
|
{ "name": "kevin", "age": 23},
|
||||||
{ "name": "kevina", "age": 21 },
|
{ "name": "kevina", "age": 21 },
|
||||||
{ "name": "benoit", "age": 34 }
|
{ "name": "benoit", "age": 34 }
|
||||||
]);
|
]))
|
||||||
let config = IndexerConfig::default();
|
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// Ensure there is no stop_words by default
|
// Ensure there is no stop_words by default
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1167,33 +1078,30 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_and_reset_stop_words() {
|
fn set_and_reset_stop_words() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
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 mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
// First we send 3 documents with ids from 1 to 3.
|
||||||
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "name": "kevin", "age": 23, "maxim": "I love dogs" },
|
{ "name": "kevin", "age": 23, "maxim": "I love dogs" },
|
||||||
{ "name": "kevina", "age": 21, "maxim": "Doggos are the best" },
|
{ "name": "kevina", "age": 21, "maxim": "Doggos are the best" },
|
||||||
{ "name": "benoit", "age": 34, "maxim": "The crepes are really good" },
|
{ "name": "benoit", "age": 34, "maxim": "The crepes are really good" },
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// In the same transaction we provide some stop_words
|
// In the same transaction we provide some stop_words
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
|
||||||
let set = btreeset! { "i".to_string(), "the".to_string(), "are".to_string() };
|
let set = btreeset! { "i".to_string(), "the".to_string(), "are".to_string() };
|
||||||
builder.set_stop_words(set.clone());
|
index
|
||||||
builder.execute(|_| ()).unwrap();
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
|
settings.set_stop_words(set.clone());
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// Ensure stop_words are effectively stored
|
// Ensure stop_words are effectively stored
|
||||||
@ -1220,11 +1128,11 @@ mod tests {
|
|||||||
assert_eq!(result.documents_ids.len(), 1); // there is one benoit in our data
|
assert_eq!(result.documents_ids.len(), 1); // there is one benoit in our data
|
||||||
|
|
||||||
// now we'll reset the stop_words and ensure it's None
|
// now we'll reset the stop_words and ensure it's None
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.reset_stop_words();
|
settings.reset_stop_words();
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let stop_words = index.stop_words(&rtxn).unwrap();
|
let stop_words = index.stop_words(&rtxn).unwrap();
|
||||||
@ -1247,36 +1155,32 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_and_reset_synonyms() {
|
fn set_and_reset_synonyms() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
|
|
||||||
// Send 3 documents with ids from 1 to 3.
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let content = documents!([
|
// Send 3 documents with ids from 1 to 3.
|
||||||
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "name": "kevin", "age": 23, "maxim": "I love dogs"},
|
{ "name": "kevin", "age": 23, "maxim": "I love dogs"},
|
||||||
{ "name": "kevina", "age": 21, "maxim": "Doggos are the best"},
|
{ "name": "kevina", "age": 21, "maxim": "Doggos are the best"},
|
||||||
{ "name": "benoit", "age": 34, "maxim": "The crepes are really good"},
|
{ "name": "benoit", "age": 34, "maxim": "The crepes are really good"},
|
||||||
]);
|
]),
|
||||||
let config = IndexerConfig::default();
|
)
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
|
|
||||||
// In the same transaction provide some synonyms
|
// In the same transaction provide some synonyms
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
index
|
||||||
builder.set_synonyms(hashmap! {
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
|
settings.set_synonyms(hashmap! {
|
||||||
"blini".to_string() => vec!["crepes".to_string()],
|
"blini".to_string() => vec!["crepes".to_string()],
|
||||||
"super like".to_string() => vec!["love".to_string()],
|
"super like".to_string() => vec!["love".to_string()],
|
||||||
"puppies".to_string() => vec!["dogs".to_string(), "doggos".to_string()]
|
"puppies".to_string() => vec!["dogs".to_string(), "doggos".to_string()]
|
||||||
});
|
});
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// Ensure synonyms are effectively stored
|
// Ensure synonyms are effectively stored
|
||||||
@ -1293,11 +1197,11 @@ mod tests {
|
|||||||
assert_eq!(result.documents_ids.len(), 2);
|
assert_eq!(result.documents_ids.len(), 2);
|
||||||
|
|
||||||
// Reset the synonyms
|
// Reset the synonyms
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.reset_synonyms();
|
settings.reset_synonyms();
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Ensure synonyms are reset
|
// Ensure synonyms are reset
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1315,20 +1219,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn setting_searchable_recomputes_other_settings() {
|
fn setting_searchable_recomputes_other_settings() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set all the settings except searchable
|
// Set all the settings except searchable
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_displayed_fields(vec!["hello".to_string()]);
|
settings.set_displayed_fields(vec!["hello".to_string()]);
|
||||||
builder.set_filterable_fields(hashset! { S("age"), S("toto") });
|
settings.set_filterable_fields(hashset! { S("age"), S("toto") });
|
||||||
builder.set_criteria(vec!["toto:asc".to_string()]);
|
settings.set_criteria(vec!["toto:asc".to_string()]);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// check the output
|
// check the output
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
@ -1339,11 +1239,11 @@ mod tests {
|
|||||||
drop(rtxn);
|
drop(rtxn);
|
||||||
|
|
||||||
// We set toto and age as searchable to force reordering of the fields
|
// We set toto and age as searchable to force reordering of the fields
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_searchable_fields(vec!["toto".to_string(), "age".to_string()]);
|
settings.set_searchable_fields(vec!["toto".to_string(), "age".to_string()]);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
assert_eq!(&["hello"][..], index.displayed_fields(&rtxn).unwrap().unwrap());
|
assert_eq!(&["hello"][..], index.displayed_fields(&rtxn).unwrap().unwrap());
|
||||||
@ -1353,20 +1253,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn setting_not_filterable_cant_filter() {
|
fn setting_not_filterable_cant_filter() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set all the settings except searchable
|
// Set all the settings except searchable
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_displayed_fields(vec!["hello".to_string()]);
|
settings.set_displayed_fields(vec!["hello".to_string()]);
|
||||||
// It is only Asc(toto), there is a facet database but it is denied to filter with toto.
|
// It is only Asc(toto), there is a facet database but it is denied to filter with toto.
|
||||||
builder.set_criteria(vec!["toto:asc".to_string()]);
|
settings.set_criteria(vec!["toto:asc".to_string()]);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
wtxn.commit().unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let filter = Filter::from_str("toto = 32").unwrap().unwrap();
|
let filter = Filter::from_str("toto = 32").unwrap().unwrap();
|
||||||
@ -1375,22 +1271,23 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn setting_primary_key() {
|
fn setting_primary_key() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the primary key settings
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
// Set the primary key settings
|
||||||
builder.set_primary_key(S("mykey"));
|
index
|
||||||
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
builder.execute(|_| ()).unwrap();
|
settings.set_primary_key(S("mykey"));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
assert_eq!(index.primary_key(&wtxn).unwrap(), Some("mykey"));
|
assert_eq!(index.primary_key(&wtxn).unwrap(), Some("mykey"));
|
||||||
|
|
||||||
// Then index some documents with the "mykey" primary key.
|
// Then index some documents with the "mykey" primary key.
|
||||||
let content = documents!([
|
index
|
||||||
|
.add_documents_using_wtxn(
|
||||||
|
&mut wtxn,
|
||||||
|
documents!([
|
||||||
{ "mykey": 1, "name": "kevin", "age": 23 },
|
{ "mykey": 1, "name": "kevin", "age": 23 },
|
||||||
{ "mykey": 2, "name": "kevina", "age": 21 },
|
{ "mykey": 2, "name": "kevina", "age": 21 },
|
||||||
{ "mykey": 3, "name": "benoit", "age": 34 },
|
{ "mykey": 3, "name": "benoit", "age": 34 },
|
||||||
@ -1398,53 +1295,47 @@ mod tests {
|
|||||||
{ "mykey": 5, "name": "bertrand", "age": 34 },
|
{ "mykey": 5, "name": "bertrand", "age": 34 },
|
||||||
{ "mykey": 6, "name": "bernie", "age": 34 },
|
{ "mykey": 6, "name": "bernie", "age": 34 },
|
||||||
{ "mykey": 7, "name": "ben", "age": 34 }
|
{ "mykey": 7, "name": "ben", "age": 34 }
|
||||||
]);
|
]),
|
||||||
let indexing_config =
|
)
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// We now try to reset the primary key
|
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
let error = index
|
||||||
builder.reset_primary_key();
|
.update_settings_using_wtxn(&mut wtxn, |settings| {
|
||||||
|
settings.reset_primary_key();
|
||||||
let err = builder.execute(|_| ()).unwrap_err();
|
})
|
||||||
assert!(matches!(err, Error::UserError(UserError::PrimaryKeyCannotBeChanged(_))));
|
.unwrap_err();
|
||||||
|
assert!(matches!(error, Error::UserError(UserError::PrimaryKeyCannotBeChanged(_))));
|
||||||
wtxn.abort().unwrap();
|
wtxn.abort().unwrap();
|
||||||
|
|
||||||
// But if we clear the database...
|
// But if we clear the database...
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
let mut wtxn = index.write_txn().unwrap();
|
||||||
let builder = ClearDocuments::new(&mut wtxn, &index);
|
let builder = ClearDocuments::new(&mut wtxn, &index);
|
||||||
builder.execute().unwrap();
|
builder.execute().unwrap();
|
||||||
|
wtxn.commit().unwrap();
|
||||||
|
|
||||||
// ...we can change the primary key
|
// ...we can change the primary key
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
index
|
||||||
builder.set_primary_key(S("myid"));
|
.update_settings(|settings| {
|
||||||
builder.execute(|_| ()).unwrap();
|
settings.set_primary_key(S("myid"));
|
||||||
wtxn.commit().unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn setting_impact_relevancy() {
|
fn setting_impact_relevancy() {
|
||||||
let path = tempfile::tempdir().unwrap();
|
let mut index = TempIndex::new();
|
||||||
let mut options = EnvOpenOptions::new();
|
index.index_documents_config.autogenerate_docids = true;
|
||||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
|
||||||
let index = Index::new(options, &path).unwrap();
|
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the genres setting
|
// Set the genres setting
|
||||||
let mut wtxn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut wtxn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_filterable_fields(hashset! { S("genres") });
|
settings.set_filterable_fields(hashset! { S("genres") });
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let content = documents!([
|
index.add_documents(documents!([
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 11,
|
||||||
"title": "Star Wars",
|
"title": "Star Wars",
|
||||||
@ -1462,18 +1353,8 @@ mod tests {
|
|||||||
"poster": "https://image.tmdb.org/t/p/w500/gSuHDeWemA1menrwfMRChnSmMVN.jpg",
|
"poster": "https://image.tmdb.org/t/p/w500/gSuHDeWemA1menrwfMRChnSmMVN.jpg",
|
||||||
"release_date": 819676800
|
"release_date": 819676800
|
||||||
}
|
}
|
||||||
]);
|
])).unwrap();
|
||||||
let indexing_config =
|
|
||||||
IndexDocumentsConfig { autogenerate_docids: true, ..Default::default() };
|
|
||||||
let builder =
|
|
||||||
IndexDocuments::new(&mut wtxn, &index, &config, indexing_config.clone(), |_| ())
|
|
||||||
.unwrap();
|
|
||||||
let (builder, user_error) = builder.add_documents(content).unwrap();
|
|
||||||
user_error.unwrap();
|
|
||||||
builder.execute().unwrap();
|
|
||||||
wtxn.commit().unwrap();
|
|
||||||
|
|
||||||
// We now try to reset the primary key
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let SearchResult { documents_ids, .. } = index.search(&rtxn).query("S").execute().unwrap();
|
let SearchResult { documents_ids, .. } = index.search(&rtxn).query("S").execute().unwrap();
|
||||||
let first_id = documents_ids[0];
|
let first_id = documents_ids[0];
|
||||||
@ -1490,45 +1371,41 @@ mod tests {
|
|||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
|
|
||||||
let mut txn = index.write_txn().unwrap();
|
let mut txn = index.write_txn().unwrap();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
assert!(index.authorize_typos(&txn).unwrap());
|
assert!(index.authorize_typos(&txn).unwrap());
|
||||||
let mut builder = Settings::new(&mut txn, &index, &config);
|
|
||||||
builder.set_autorize_typos(false);
|
index
|
||||||
builder.execute(|_| ()).unwrap();
|
.update_settings_using_wtxn(&mut txn, |settings| {
|
||||||
|
settings.set_autorize_typos(false);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert!(!index.authorize_typos(&txn).unwrap());
|
assert!(!index.authorize_typos(&txn).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn update_min_word_len_for_typo() {
|
fn update_min_word_len_for_typo() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the genres setting
|
// Set the genres setting
|
||||||
let mut txn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut txn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_min_word_len_one_typo(8);
|
settings.set_min_word_len_one_typo(8);
|
||||||
builder.set_min_word_len_two_typos(8);
|
settings.set_min_word_len_two_typos(8);
|
||||||
builder.execute(|_| ()).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
txn.commit().unwrap();
|
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
assert_eq!(index.min_word_len_one_typo(&txn).unwrap(), 8);
|
assert_eq!(index.min_word_len_one_typo(&txn).unwrap(), 8);
|
||||||
assert_eq!(index.min_word_len_two_typos(&txn).unwrap(), 8);
|
assert_eq!(index.min_word_len_two_typos(&txn).unwrap(), 8);
|
||||||
|
|
||||||
let mut txn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut txn, &index, &config);
|
.update_settings(|settings| {
|
||||||
|
settings.reset_min_word_len_one_typo();
|
||||||
builder.reset_min_word_len_one_typo();
|
settings.reset_min_word_len_two_typos();
|
||||||
builder.reset_min_word_len_two_typos();
|
})
|
||||||
builder.execute(|_| ()).unwrap();
|
.unwrap();
|
||||||
|
|
||||||
txn.commit().unwrap();
|
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
assert_eq!(index.min_word_len_one_typo(&txn).unwrap(), DEFAULT_MIN_WORD_LEN_ONE_TYPO);
|
assert_eq!(index.min_word_len_one_typo(&txn).unwrap(), DEFAULT_MIN_WORD_LEN_ONE_TYPO);
|
||||||
assert_eq!(index.min_word_len_two_typos(&txn).unwrap(), DEFAULT_MIN_WORD_LEN_TWO_TYPOS);
|
assert_eq!(index.min_word_len_two_typos(&txn).unwrap(), DEFAULT_MIN_WORD_LEN_TWO_TYPOS);
|
||||||
}
|
}
|
||||||
@ -1536,28 +1413,29 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn update_invalid_min_word_len_for_typo() {
|
fn update_invalid_min_word_len_for_typo() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the genres setting
|
// Set the genres setting
|
||||||
let mut txn = index.write_txn().unwrap();
|
index
|
||||||
let mut builder = Settings::new(&mut txn, &index, &config);
|
.update_settings(|settings| {
|
||||||
builder.set_min_word_len_one_typo(10);
|
settings.set_min_word_len_one_typo(10);
|
||||||
builder.set_min_word_len_two_typos(7);
|
settings.set_min_word_len_two_typos(7);
|
||||||
assert!(builder.execute(|_| ()).is_err());
|
})
|
||||||
|
.unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn update_exact_words_normalization() {
|
fn update_exact_words_normalization() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
// Set the genres setting
|
|
||||||
let mut txn = index.write_txn().unwrap();
|
let mut txn = index.write_txn().unwrap();
|
||||||
let mut builder = Settings::new(&mut txn, &index, &config);
|
// Set the genres setting
|
||||||
|
index
|
||||||
|
.update_settings_using_wtxn(&mut txn, |settings| {
|
||||||
let words = btreeset! { S("Ab"), S("ac") };
|
let words = btreeset! { S("Ab"), S("ac") };
|
||||||
builder.set_exact_words(words);
|
settings.set_exact_words(words);
|
||||||
assert!(builder.execute(|_| ()).is_ok());
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let exact_words = index.exact_words(&txn).unwrap().unwrap();
|
let exact_words = index.exact_words(&txn).unwrap().unwrap();
|
||||||
for word in exact_words.into_fst().stream().into_str_vec().unwrap() {
|
for word in exact_words.into_fst().stream().into_str_vec().unwrap() {
|
||||||
assert!(word.0 == "ac" || word.0 == "ab");
|
assert!(word.0 == "ac" || word.0 == "ab");
|
||||||
@ -1567,10 +1445,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_correct_settings_init() {
|
fn test_correct_settings_init() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
let config = IndexerConfig::default();
|
|
||||||
|
|
||||||
let mut txn = index.write_txn().unwrap();
|
index
|
||||||
let builder = Settings::new(&mut txn, &index, &config);
|
.update_settings(|settings| {
|
||||||
|
// we don't actually update the settings, just check their content
|
||||||
let Settings {
|
let Settings {
|
||||||
wtxn: _,
|
wtxn: _,
|
||||||
index: _,
|
index: _,
|
||||||
@ -1591,8 +1469,7 @@ mod tests {
|
|||||||
exact_attributes,
|
exact_attributes,
|
||||||
max_values_per_facet,
|
max_values_per_facet,
|
||||||
pagination_max_total_hits,
|
pagination_max_total_hits,
|
||||||
} = builder;
|
} = settings;
|
||||||
|
|
||||||
assert!(matches!(searchable_fields, Setting::NotSet));
|
assert!(matches!(searchable_fields, Setting::NotSet));
|
||||||
assert!(matches!(displayed_fields, Setting::NotSet));
|
assert!(matches!(displayed_fields, Setting::NotSet));
|
||||||
assert!(matches!(filterable_fields, Setting::NotSet));
|
assert!(matches!(filterable_fields, Setting::NotSet));
|
||||||
@ -1609,5 +1486,7 @@ mod tests {
|
|||||||
assert!(matches!(exact_attributes, Setting::NotSet));
|
assert!(matches!(exact_attributes, Setting::NotSet));
|
||||||
assert!(matches!(max_values_per_facet, Setting::NotSet));
|
assert!(matches!(max_values_per_facet, Setting::NotSet));
|
||||||
assert!(matches!(pagination_max_total_hits, Setting::NotSet));
|
assert!(matches!(pagination_max_total_hits, Setting::NotSet));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user