mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-03 11:57:07 +02:00
Test and implement settings opt-out
This commit is contained in:
parent
5560452ef9
commit
d66dc363ed
36 changed files with 1018 additions and 94 deletions
|
@ -369,6 +369,30 @@ make_setting_route!(
|
|||
SearchCutoffMsAnalytics
|
||||
);
|
||||
|
||||
make_setting_route!(
|
||||
"/facet-search",
|
||||
put,
|
||||
bool,
|
||||
meilisearch_types::deserr::DeserrJsonError<
|
||||
meilisearch_types::error::deserr_codes::InvalidSettingsFacetSearch,
|
||||
>,
|
||||
facet_search,
|
||||
"facetSearch",
|
||||
FacetSearchAnalytics
|
||||
);
|
||||
|
||||
make_setting_route!(
|
||||
"/prefix-search",
|
||||
put,
|
||||
meilisearch_types::settings::PrefixSearchSettings,
|
||||
meilisearch_types::deserr::DeserrJsonError<
|
||||
meilisearch_types::error::deserr_codes::InvalidSettingsPrefixSearch,
|
||||
>,
|
||||
prefix_search,
|
||||
"prefixSearch",
|
||||
PrefixSearchAnalytics
|
||||
);
|
||||
|
||||
macro_rules! generate_configure {
|
||||
($($mod:ident),*) => {
|
||||
pub fn configure(cfg: &mut web::ServiceConfig) {
|
||||
|
@ -456,6 +480,8 @@ pub async fn update_all(
|
|||
non_separator_tokens: NonSeparatorTokensAnalytics::new(
|
||||
new_settings.non_separator_tokens.as_ref().set(),
|
||||
),
|
||||
facet_search: FacetSearchAnalytics::new(new_settings.facet_search.as_ref().set()),
|
||||
prefix_search: PrefixSearchAnalytics::new(new_settings.prefix_search.as_ref().set()),
|
||||
},
|
||||
&req,
|
||||
);
|
||||
|
|
|
@ -10,7 +10,8 @@ use meilisearch_types::locales::{Locale, LocalizedAttributesRuleView};
|
|||
use meilisearch_types::milli::update::Setting;
|
||||
use meilisearch_types::milli::vector::settings::EmbeddingSettings;
|
||||
use meilisearch_types::settings::{
|
||||
FacetingSettings, PaginationSettings, ProximityPrecisionView, RankingRuleView, TypoSettings,
|
||||
FacetingSettings, PaginationSettings, PrefixSearchSettings, ProximityPrecisionView,
|
||||
RankingRuleView, TypoSettings,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -36,6 +37,8 @@ pub struct SettingsAnalytics {
|
|||
pub dictionary: DictionaryAnalytics,
|
||||
pub separator_tokens: SeparatorTokensAnalytics,
|
||||
pub non_separator_tokens: NonSeparatorTokensAnalytics,
|
||||
pub facet_search: FacetSearchAnalytics,
|
||||
pub prefix_search: PrefixSearchAnalytics,
|
||||
}
|
||||
|
||||
impl Aggregate for SettingsAnalytics {
|
||||
|
@ -183,6 +186,14 @@ impl Aggregate for SettingsAnalytics {
|
|||
non_separator_tokens: NonSeparatorTokensAnalytics {
|
||||
total: new.non_separator_tokens.total.or(self.non_separator_tokens.total),
|
||||
},
|
||||
facet_search: FacetSearchAnalytics {
|
||||
set: new.facet_search.set | self.facet_search.set,
|
||||
value: new.facet_search.value.or(self.facet_search.value),
|
||||
},
|
||||
prefix_search: PrefixSearchAnalytics {
|
||||
set: new.prefix_search.set | self.prefix_search.set,
|
||||
value: new.prefix_search.value.or(self.prefix_search.value),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -620,3 +631,35 @@ impl NonSeparatorTokensAnalytics {
|
|||
SettingsAnalytics { non_separator_tokens: self, ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Default)]
|
||||
pub struct FacetSearchAnalytics {
|
||||
pub set: bool,
|
||||
pub value: Option<bool>,
|
||||
}
|
||||
|
||||
impl FacetSearchAnalytics {
|
||||
pub fn new(settings: Option<&bool>) -> Self {
|
||||
Self { set: settings.is_some(), value: settings.copied() }
|
||||
}
|
||||
|
||||
pub fn into_settings(self) -> SettingsAnalytics {
|
||||
SettingsAnalytics { facet_search: self, ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Default)]
|
||||
pub struct PrefixSearchAnalytics {
|
||||
pub set: bool,
|
||||
pub value: Option<PrefixSearchSettings>,
|
||||
}
|
||||
|
||||
impl PrefixSearchAnalytics {
|
||||
pub fn new(settings: Option<&PrefixSearchSettings>) -> Self {
|
||||
Self { set: settings.is_some(), value: settings.cloned() }
|
||||
}
|
||||
|
||||
pub fn into_settings(self) -> SettingsAnalytics {
|
||||
SettingsAnalytics { prefix_search: self, ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,9 @@ async fn import_dump_v1_movie_raw() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -242,7 +244,9 @@ async fn import_dump_v1_movie_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -391,7 +395,9 @@ async fn import_dump_v1_rubygems_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -526,7 +532,9 @@ async fn import_dump_v2_movie_raw() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -673,7 +681,9 @@ async fn import_dump_v2_movie_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -819,7 +829,9 @@ async fn import_dump_v2_rubygems_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -954,7 +966,9 @@ async fn import_dump_v3_movie_raw() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1101,7 +1115,9 @@ async fn import_dump_v3_movie_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1247,7 +1263,9 @@ async fn import_dump_v3_rubygems_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1382,7 +1400,9 @@ async fn import_dump_v4_movie_raw() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1529,7 +1549,9 @@ async fn import_dump_v4_movie_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1675,7 +1697,9 @@ async fn import_dump_v4_rubygems_with_settings() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###
|
||||
);
|
||||
|
@ -1922,7 +1946,9 @@ async fn import_dump_v6_containing_experimental_features() {
|
|||
"maxTotalHits": 1000
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###);
|
||||
|
||||
|
@ -2102,7 +2128,9 @@ async fn generate_and_import_dump_containing_vectors() {
|
|||
}
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###);
|
||||
|
||||
|
|
|
@ -200,3 +200,115 @@ async fn simple_facet_search_with_sort_by_count() {
|
|||
assert_eq!(hits[0], json!({ "value": "Action", "count": 3 }));
|
||||
assert_eq!(hits[1], json!({ "value": "Adventure", "count": 2 }));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn add_documents_and_deactivate_facet_search() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let documents = DOCUMENTS.clone();
|
||||
index.add_documents(documents, None).await;
|
||||
index.wait_task(0).await;
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": false,
|
||||
"filterableAttributes": ["genres"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) =
|
||||
index.facet_search(json!({"facetName": "genres", "facetQuery": "a"})).await;
|
||||
|
||||
assert_eq!(code, 200, "{}", response);
|
||||
assert_eq!(dbg!(response)["facetHits"].as_array().unwrap().len(), 0);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn deactivate_facet_search_and_add_documents() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": false,
|
||||
"filterableAttributes": ["genres"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
let documents = DOCUMENTS.clone();
|
||||
index.add_documents(documents, None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) =
|
||||
index.facet_search(json!({"facetName": "genres", "facetQuery": "a"})).await;
|
||||
|
||||
assert_eq!(code, 200, "{}", response);
|
||||
assert_eq!(dbg!(response)["facetHits"].as_array().unwrap().len(), 0);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn deactivate_facet_search_add_documents_and_activate_facet_search() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": false,
|
||||
"filterableAttributes": ["genres"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
let documents = DOCUMENTS.clone();
|
||||
index.add_documents(documents, None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": true,
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(2).await;
|
||||
|
||||
let (response, code) =
|
||||
index.facet_search(json!({"facetName": "genres", "facetQuery": "a"})).await;
|
||||
|
||||
assert_eq!(code, 200, "{}", response);
|
||||
assert_eq!(dbg!(response)["facetHits"].as_array().unwrap().len(), 2);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn deactivate_facet_search_add_documents_and_reset_facet_search() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": false,
|
||||
"filterableAttributes": ["genres"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
let documents = DOCUMENTS.clone();
|
||||
index.add_documents(documents, None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"facetSearch": serde_json::Value::Null,
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(2).await;
|
||||
|
||||
let (response, code) =
|
||||
index.facet_search(json!({"facetName": "genres", "facetQuery": "a"})).await;
|
||||
|
||||
assert_eq!(code, 200, "{}", response);
|
||||
assert_eq!(dbg!(response)["facetHits"].as_array().unwrap().len(), 2);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ async fn get_settings() {
|
|||
let (response, code) = index.settings().await;
|
||||
assert_eq!(code, 200);
|
||||
let settings = response.as_object().unwrap();
|
||||
assert_eq!(settings.keys().len(), 17);
|
||||
assert_eq!(settings.keys().len(), 19);
|
||||
assert_eq!(settings["displayedAttributes"], json!(["*"]));
|
||||
assert_eq!(settings["searchableAttributes"], json!(["*"]));
|
||||
assert_eq!(settings["filterableAttributes"], json!([]));
|
||||
|
@ -87,6 +87,8 @@ async fn get_settings() {
|
|||
);
|
||||
assert_eq!(settings["proximityPrecision"], json!("byWord"));
|
||||
assert_eq!(settings["searchCutoffMs"], json!(null));
|
||||
assert_eq!(settings["prefixSearch"], json!("indexingTime"));
|
||||
assert_eq!(settings["facetSearch"], json!(true));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
|
@ -199,7 +201,9 @@ async fn secrets_are_hidden_in_settings() {
|
|||
}
|
||||
},
|
||||
"searchCutoffMs": null,
|
||||
"localizedAttributes": null
|
||||
"localizedAttributes": null,
|
||||
"facetSearch": true,
|
||||
"prefixSearch": "indexingTime"
|
||||
}
|
||||
"###);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod distinct;
|
||||
mod errors;
|
||||
mod get_settings;
|
||||
mod prefix_search_settings;
|
||||
mod proximity_settings;
|
||||
mod tokenizer_customization;
|
||||
|
|
458
crates/meilisearch/tests/settings/prefix_search_settings.rs
Normal file
458
crates/meilisearch/tests/settings/prefix_search_settings.rs
Normal file
|
@ -0,0 +1,458 @@
|
|||
use meili_snap::{json_string, snapshot};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::common::Server;
|
||||
use crate::json;
|
||||
|
||||
static DOCUMENTS: Lazy<crate::common::Value> = Lazy::new(|| {
|
||||
json!([
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
},
|
||||
])
|
||||
});
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn add_docs_and_disable() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
index.add_documents(DOCUMENTS.clone(), None).await;
|
||||
index.wait_task(0).await;
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": "disabled",
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(1).await;
|
||||
|
||||
// only 1 document should match
|
||||
index
|
||||
.search(json!({"q": "so", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day <em>so</em>",
|
||||
"b": "manythe manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
|
||||
// only 1 document should match
|
||||
index
|
||||
.search(json!({"q": "manythe", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day so",
|
||||
"b": "<em>manythe</em> manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn disable_and_add_docs() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": "disabled",
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
|
||||
index.add_documents(DOCUMENTS.clone(), None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
// only 1 document should match
|
||||
index
|
||||
.search(json!({"q": "so", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day <em>so</em>",
|
||||
"b": "manythe manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
|
||||
index
|
||||
.search(json!({"q": "manythe", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day so",
|
||||
"b": "<em>manythe</em> manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn disable_add_docs_and_enable() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": "disabled",
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
|
||||
index.add_documents(DOCUMENTS.clone(), None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": "indexingTime",
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(2).await;
|
||||
|
||||
// all documents should match
|
||||
index
|
||||
.search(json!({"q": "so", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "<em>So</em>up of the day",
|
||||
"b": "manythefishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "<em>So</em>up of day <em>so</em>",
|
||||
"b": "manythe manythelazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the <em>So</em>up of day",
|
||||
"b": "manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
|
||||
index
|
||||
.search(json!({"q": "manythe", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "Soup of the day",
|
||||
"b": "<em>manythe</em>fishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day so",
|
||||
"b": "<em>manythe</em> <em>manythe</em>lazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the Soup of day",
|
||||
"b": "<em>manythe</em>lazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn disable_add_docs_and_reset() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": "disabled",
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
|
||||
index.add_documents(DOCUMENTS.clone(), None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"prefixSearch": serde_json::Value::Null,
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(2).await;
|
||||
|
||||
// all documents should match
|
||||
index
|
||||
.search(json!({"q": "so", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "<em>So</em>up of the day",
|
||||
"b": "manythefishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "<em>So</em>up of day <em>so</em>",
|
||||
"b": "manythe manythelazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the <em>So</em>up of day",
|
||||
"b": "manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
|
||||
index
|
||||
.search(json!({"q": "manythe", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "Soup of the day",
|
||||
"b": "<em>manythe</em>fishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day so",
|
||||
"b": "<em>manythe</em> <em>manythe</em>lazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the Soup of day",
|
||||
"b": "<em>manythe</em>lazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn default_behavior() {
|
||||
let server = Server::new().await;
|
||||
let index = server.index("test");
|
||||
|
||||
let (response, code) = index
|
||||
.update_settings(json!({
|
||||
"rankingRules": ["words", "typo", "proximity"],
|
||||
}))
|
||||
.await;
|
||||
assert_eq!("202", code.as_str(), "{:?}", response);
|
||||
index.wait_task(0).await;
|
||||
|
||||
index.add_documents(DOCUMENTS.clone(), None).await;
|
||||
index.wait_task(1).await;
|
||||
|
||||
// all documents should match
|
||||
index
|
||||
.search(json!({"q": "so", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "<em>So</em>up of the day",
|
||||
"b": "manythefishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "<em>So</em>up of day <em>so</em>",
|
||||
"b": "manythe manythelazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the <em>So</em>up of day",
|
||||
"b": "manythelazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
|
||||
index
|
||||
.search(json!({"q": "manythe", "attributesToHighlight": ["a", "b"]}), |response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"a": "Soup of the day",
|
||||
"b": "manythefishou",
|
||||
"_formatted": {
|
||||
"id": "1",
|
||||
"a": "Soup of the day",
|
||||
"b": "<em>manythe</em>fishou"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"a": "Soup of day so",
|
||||
"b": "manythe manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "2",
|
||||
"a": "Soup of day so",
|
||||
"b": "<em>manythe</em> <em>manythe</em>lazyfish"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"a": "the Soup of day",
|
||||
"b": "manythelazyfish",
|
||||
"_formatted": {
|
||||
"id": "3",
|
||||
"a": "the Soup of day",
|
||||
"b": "<em>manythe</em>lazyfish"
|
||||
}
|
||||
}
|
||||
]
|
||||
"###);
|
||||
})
|
||||
.await;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue