mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-12-23 12:57:17 +00:00
Compare commits
1 Commits
main
...
log-search
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac76f243c7 |
@@ -172,7 +172,8 @@ pub fn run_benches(c: &mut criterion::Criterion, confs: &[Conf]) {
|
|||||||
|b, &query| {
|
|b, &query| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let mut search = index.search(&rtxn);
|
let progress = Progress::default();
|
||||||
|
let mut search = index.search(&rtxn, &progress);
|
||||||
search
|
search
|
||||||
.query(query)
|
.query(query)
|
||||||
.terms_matching_strategy(TermsMatchingStrategy::default());
|
.terms_matching_strategy(TermsMatchingStrategy::default());
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// after executing a batch we check if the database is corrupted
|
// after executing a batch we check if the database is corrupted
|
||||||
let res = index.search(&wtxn).execute().unwrap();
|
let progress = Progress::default();
|
||||||
|
let res = index.search(&wtxn, &progress).execute().unwrap();
|
||||||
index.documents(&wtxn, res.documents_ids).unwrap();
|
index.documents(&wtxn, res.documents_ids).unwrap();
|
||||||
progression.fetch_add(1, Ordering::Relaxed);
|
progression.fetch_add(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use meilisearch_types::error::{Code, ErrorCode, ResponseError};
|
use meilisearch_types::error::{Code, ErrorCode, ResponseError};
|
||||||
use meilisearch_types::milli::TimeBudget;
|
use meilisearch_types::milli::progress::Progress;
|
||||||
|
use meilisearch_types::milli::{SearchStep, TimeBudget};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -346,9 +347,11 @@ impl PersonalizationService {
|
|||||||
personalize: &Personalize,
|
personalize: &Personalize,
|
||||||
query: Option<&str>,
|
query: Option<&str>,
|
||||||
time_budget: TimeBudget,
|
time_budget: TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<SearchResult, ResponseError> {
|
) -> Result<SearchResult, ResponseError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Cohere(cohere_service) => {
|
Self::Cohere(cohere_service) => {
|
||||||
|
let _ = progress.update_progress_scoped(SearchStep::ApplyingPersonalization);
|
||||||
cohere_service
|
cohere_service
|
||||||
.rerank_search_results(search_result, personalize, query, time_budget)
|
.rerank_search_results(search_result, personalize, query, time_budget)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ use meilisearch_types::features::{
|
|||||||
use meilisearch_types::heed::RoTxn;
|
use meilisearch_types::heed::RoTxn;
|
||||||
use meilisearch_types::keys::actions;
|
use meilisearch_types::keys::actions;
|
||||||
use meilisearch_types::milli::index::ChatConfig;
|
use meilisearch_types::milli::index::ChatConfig;
|
||||||
use meilisearch_types::milli::{all_obkv_to_json, obkv_to_json, OrderBy, PatternMatch, TimeBudget};
|
use meilisearch_types::milli::progress::Progress;
|
||||||
|
use meilisearch_types::milli::{
|
||||||
|
all_obkv_to_json, obkv_to_json, OrderBy, PatternMatch, TimeBudget,
|
||||||
|
TotalProcessingTimeStep,
|
||||||
|
};
|
||||||
use meilisearch_types::{Document, Index};
|
use meilisearch_types::{Document, Index};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@@ -262,6 +266,7 @@ async fn process_search_request(
|
|||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
) -> Result<(Index, Vec<Document>, String), ResponseError> {
|
) -> Result<(Index, Vec<Document>, String), ResponseError> {
|
||||||
let index = index_scheduler.index(&index_uid)?;
|
let index = index_scheduler.index(&index_uid)?;
|
||||||
|
let progress = Progress::default();
|
||||||
let rtxn = index.static_read_txn()?;
|
let rtxn = index.static_read_txn()?;
|
||||||
let ChatConfig { description: _, prompt: _, search_parameters } = index.chat_config(&rtxn)?;
|
let ChatConfig { description: _, prompt: _, search_parameters } = index.chat_config(&rtxn)?;
|
||||||
let mut query = SearchQuery {
|
let mut query = SearchQuery {
|
||||||
@@ -285,7 +290,9 @@ async fn process_search_request(
|
|||||||
let search_kind =
|
let search_kind =
|
||||||
search_kind(&query, index_scheduler.get_ref(), index_uid.to_string(), &index)?;
|
search_kind(&query, index_scheduler.get_ref(), index_uid.to_string(), &index)?;
|
||||||
|
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::WaitingForPermit);
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::Searching);
|
||||||
let features = index_scheduler.features();
|
let features = index_scheduler.features();
|
||||||
let index_cloned = index.clone();
|
let index_cloned = index.clone();
|
||||||
let output = tokio::task::spawn_blocking(move || -> Result<_, ResponseError> {
|
let output = tokio::task::spawn_blocking(move || -> Result<_, ResponseError> {
|
||||||
@@ -297,8 +304,15 @@ async fn process_search_request(
|
|||||||
None => TimeBudget::default(),
|
None => TimeBudget::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (search, _is_finite_pagination, _max_total_hits, _offset) =
|
let (search, _is_finite_pagination, _max_total_hits, _offset) = prepare_search(
|
||||||
prepare_search(&index_cloned, &rtxn, &query, &search_kind, time_budget, features)?;
|
&index_cloned,
|
||||||
|
&rtxn,
|
||||||
|
&query,
|
||||||
|
&search_kind,
|
||||||
|
time_budget,
|
||||||
|
features,
|
||||||
|
&progress,
|
||||||
|
)?;
|
||||||
|
|
||||||
match search_from_kind(index_uid, search_kind, search) {
|
match search_from_kind(index_uid, search_kind, search) {
|
||||||
Ok((search_results, _)) => Ok((rtxn, Ok(search_results))),
|
Ok((search_results, _)) => Ok((rtxn, Ok(search_results))),
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ use meilisearch_types::error::deserr_codes::*;
|
|||||||
use meilisearch_types::error::ResponseError;
|
use meilisearch_types::error::ResponseError;
|
||||||
use meilisearch_types::index_uid::IndexUid;
|
use meilisearch_types::index_uid::IndexUid;
|
||||||
use meilisearch_types::locales::Locale;
|
use meilisearch_types::locales::Locale;
|
||||||
use meilisearch_types::milli;
|
use meilisearch_types::milli::progress::Progress;
|
||||||
|
use meilisearch_types::milli::{self, TotalProcessingTimeStep};
|
||||||
use meilisearch_types::serde_cs::vec::CS;
|
use meilisearch_types::serde_cs::vec::CS;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -336,6 +337,10 @@ pub async fn search_with_url_query(
|
|||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let request_uid = Uuid::now_v7();
|
let request_uid = Uuid::now_v7();
|
||||||
debug!(request_uid = ?request_uid, parameters = ?params, "Search get");
|
debug!(request_uid = ?request_uid, parameters = ?params, "Search get");
|
||||||
|
let progress = Progress::default();
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::WaitingForPermit);
|
||||||
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::Searching);
|
||||||
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
||||||
|
|
||||||
let mut query: SearchQuery = params.into_inner().try_into()?;
|
let mut query: SearchQuery = params.into_inner().try_into()?;
|
||||||
@@ -359,9 +364,9 @@ pub async fn search_with_url_query(
|
|||||||
// Save the query string for personalization if requested
|
// Save the query string for personalization if requested
|
||||||
let personalize_query = personalize.is_some().then(|| query.q.clone()).flatten();
|
let personalize_query = personalize.is_some().then(|| query.q.clone()).flatten();
|
||||||
|
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
|
||||||
let include_metadata = parse_include_metadata_header(&req);
|
let include_metadata = parse_include_metadata_header(&req);
|
||||||
|
|
||||||
|
let progress_clone = progress.clone();
|
||||||
let search_result = tokio::task::spawn_blocking(move || {
|
let search_result = tokio::task::spawn_blocking(move || {
|
||||||
perform_search(
|
perform_search(
|
||||||
SearchParams {
|
SearchParams {
|
||||||
@@ -374,15 +379,21 @@ pub async fn search_with_url_query(
|
|||||||
include_metadata,
|
include_metadata,
|
||||||
},
|
},
|
||||||
&index,
|
&index,
|
||||||
|
&progress_clone,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
permit.drop().await;
|
permit.drop().await;
|
||||||
let search_result = search_result?;
|
let search_result = search_result?;
|
||||||
|
|
||||||
|
let analytics_step =
|
||||||
|
progress.update_progress_scoped(TotalProcessingTimeStep::PublishingAnalytics);
|
||||||
if let Ok((search_result, _)) = search_result.as_ref() {
|
if let Ok((search_result, _)) = search_result.as_ref() {
|
||||||
aggregate.succeed(search_result);
|
aggregate.succeed(search_result);
|
||||||
}
|
}
|
||||||
analytics.publish(aggregate, &req);
|
analytics.publish(aggregate, &req);
|
||||||
|
// early finish progress step
|
||||||
|
drop(analytics_step);
|
||||||
|
|
||||||
let (mut search_result, time_budget) = search_result?;
|
let (mut search_result, time_budget) = search_result?;
|
||||||
|
|
||||||
@@ -394,11 +405,12 @@ pub async fn search_with_url_query(
|
|||||||
personalize,
|
personalize,
|
||||||
personalize_query.as_deref(),
|
personalize_query.as_deref(),
|
||||||
time_budget,
|
time_budget,
|
||||||
|
&progress,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(request_uid = ?request_uid, returns = ?search_result, "Search get");
|
debug!(request_uid = ?request_uid, returns = ?search_result, progress = ?progress.accumulated_durations(), "Search get");
|
||||||
Ok(HttpResponse::Ok().json(search_result))
|
Ok(HttpResponse::Ok().json(search_result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,6 +482,11 @@ pub async fn search_with_post(
|
|||||||
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
||||||
let request_uid = Uuid::now_v7();
|
let request_uid = Uuid::now_v7();
|
||||||
|
|
||||||
|
let progress = Progress::default();
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::WaitingForPermit);
|
||||||
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::Searching);
|
||||||
|
|
||||||
let mut query = params.into_inner();
|
let mut query = params.into_inner();
|
||||||
debug!(request_uid = ?request_uid, parameters = ?query, "Search post");
|
debug!(request_uid = ?request_uid, parameters = ?query, "Search post");
|
||||||
|
|
||||||
@@ -494,7 +511,7 @@ pub async fn search_with_post(
|
|||||||
// Save the query string for personalization if requested
|
// Save the query string for personalization if requested
|
||||||
let personalize_query = personalize.is_some().then(|| query.q.clone()).flatten();
|
let personalize_query = personalize.is_some().then(|| query.q.clone()).flatten();
|
||||||
|
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
let progress_clone = progress.clone();
|
||||||
let search_result = tokio::task::spawn_blocking(move || {
|
let search_result = tokio::task::spawn_blocking(move || {
|
||||||
perform_search(
|
perform_search(
|
||||||
SearchParams {
|
SearchParams {
|
||||||
@@ -507,11 +524,14 @@ pub async fn search_with_post(
|
|||||||
include_metadata,
|
include_metadata,
|
||||||
},
|
},
|
||||||
&index,
|
&index,
|
||||||
|
&progress_clone,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
permit.drop().await;
|
permit.drop().await;
|
||||||
let search_result = search_result?;
|
let search_result = search_result?;
|
||||||
|
let analytics_step =
|
||||||
|
progress.update_progress_scoped(TotalProcessingTimeStep::PublishingAnalytics);
|
||||||
if let Ok((ref search_result, _)) = search_result {
|
if let Ok((ref search_result, _)) = search_result {
|
||||||
aggregate.succeed(search_result);
|
aggregate.succeed(search_result);
|
||||||
if search_result.degraded {
|
if search_result.degraded {
|
||||||
@@ -519,6 +539,8 @@ pub async fn search_with_post(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
analytics.publish(aggregate, &req);
|
analytics.publish(aggregate, &req);
|
||||||
|
// early finish progress step
|
||||||
|
drop(analytics_step);
|
||||||
|
|
||||||
let (mut search_result, time_budget) = search_result?;
|
let (mut search_result, time_budget) = search_result?;
|
||||||
|
|
||||||
@@ -530,11 +552,12 @@ pub async fn search_with_post(
|
|||||||
personalize,
|
personalize,
|
||||||
personalize_query.as_deref(),
|
personalize_query.as_deref(),
|
||||||
time_budget,
|
time_budget,
|
||||||
|
&progress,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(request_uid = ?request_uid, returns = ?search_result, "Search post");
|
debug!(request_uid = ?request_uid, returns = ?search_result, progress = ?progress.accumulated_durations(), "Search post");
|
||||||
Ok(HttpResponse::Ok().json(search_result))
|
Ok(HttpResponse::Ok().json(search_result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use meilisearch_types::error::deserr_codes::*;
|
|||||||
use meilisearch_types::error::ResponseError;
|
use meilisearch_types::error::ResponseError;
|
||||||
use meilisearch_types::index_uid::IndexUid;
|
use meilisearch_types::index_uid::IndexUid;
|
||||||
use meilisearch_types::keys::actions;
|
use meilisearch_types::keys::actions;
|
||||||
|
use meilisearch_types::milli::progress::Progress;
|
||||||
|
use meilisearch_types::milli::TotalProcessingTimeStep;
|
||||||
use meilisearch_types::serde_cs::vec::CS;
|
use meilisearch_types::serde_cs::vec::CS;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -217,7 +219,7 @@ async fn similar(
|
|||||||
mut query: SimilarQuery,
|
mut query: SimilarQuery,
|
||||||
) -> Result<SimilarResult, ResponseError> {
|
) -> Result<SimilarResult, ResponseError> {
|
||||||
let retrieve_vectors = RetrieveVectors::new(query.retrieve_vectors);
|
let retrieve_vectors = RetrieveVectors::new(query.retrieve_vectors);
|
||||||
|
let progress = Progress::default();
|
||||||
// Tenant token search_rules.
|
// Tenant token search_rules.
|
||||||
if let Some(search_rules) = index_scheduler.filters().get_index_search_rules(&index_uid) {
|
if let Some(search_rules) = index_scheduler.filters().get_index_search_rules(&index_uid) {
|
||||||
add_search_rules(&mut query.filter, search_rules);
|
add_search_rules(&mut query.filter, search_rules);
|
||||||
@@ -234,7 +236,10 @@ async fn similar(
|
|||||||
Route::Similar,
|
Route::Similar,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
let progress_clone = progress.clone();
|
||||||
|
let result = tokio::task::spawn_blocking(move || {
|
||||||
|
let _step = progress_clone.update_progress_scoped(TotalProcessingTimeStep::Searching);
|
||||||
|
|
||||||
perform_similar(
|
perform_similar(
|
||||||
&index,
|
&index,
|
||||||
query,
|
query,
|
||||||
@@ -243,9 +248,14 @@ async fn similar(
|
|||||||
quantized,
|
quantized,
|
||||||
retrieve_vectors,
|
retrieve_vectors,
|
||||||
index_scheduler.features(),
|
index_scheduler.features(),
|
||||||
|
&progress_clone,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await?
|
.await;
|
||||||
|
|
||||||
|
debug!(progress = ?progress.accumulated_durations(), "Similar");
|
||||||
|
|
||||||
|
result?
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, deserr::Deserr, IntoParams)]
|
#[derive(Debug, deserr::Deserr, IntoParams)]
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ use index_scheduler::IndexScheduler;
|
|||||||
use meilisearch_types::deserr::DeserrJsonError;
|
use meilisearch_types::deserr::DeserrJsonError;
|
||||||
use meilisearch_types::error::ResponseError;
|
use meilisearch_types::error::ResponseError;
|
||||||
use meilisearch_types::keys::actions;
|
use meilisearch_types::keys::actions;
|
||||||
|
use meilisearch_types::milli::progress::Progress;
|
||||||
|
use meilisearch_types::milli::TotalProcessingTimeStep;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use utoipa::{OpenApi, ToSchema};
|
use utoipa::{OpenApi, ToSchema};
|
||||||
@@ -153,7 +155,10 @@ pub async fn multi_search_with_post(
|
|||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
// Since we don't want to process half of the search requests and then get a permit refused
|
// Since we don't want to process half of the search requests and then get a permit refused
|
||||||
// we're going to get one permit for the whole duration of the multi-search request.
|
// we're going to get one permit for the whole duration of the multi-search request.
|
||||||
|
let progress = Progress::default();
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::WaitingForPermit);
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
|
progress.update_progress(TotalProcessingTimeStep::Searching);
|
||||||
let request_uid = Uuid::now_v7();
|
let request_uid = Uuid::now_v7();
|
||||||
|
|
||||||
let federated_search = params.into_inner();
|
let federated_search = params.into_inner();
|
||||||
@@ -213,6 +218,7 @@ pub async fn multi_search_with_post(
|
|||||||
is_proxy,
|
is_proxy,
|
||||||
request_uid,
|
request_uid,
|
||||||
include_metadata,
|
include_metadata,
|
||||||
|
&progress,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
permit.drop().await;
|
permit.drop().await;
|
||||||
@@ -288,6 +294,7 @@ pub async fn multi_search_with_post(
|
|||||||
.with_index(query_index)?;
|
.with_index(query_index)?;
|
||||||
let retrieve_vector = RetrieveVectors::new(query.retrieve_vectors);
|
let retrieve_vector = RetrieveVectors::new(query.retrieve_vectors);
|
||||||
|
|
||||||
|
let progress_clone = progress.clone();
|
||||||
let (mut search_result, time_budget) = tokio::task::spawn_blocking(move || {
|
let (mut search_result, time_budget) = tokio::task::spawn_blocking(move || {
|
||||||
perform_search(
|
perform_search(
|
||||||
SearchParams {
|
SearchParams {
|
||||||
@@ -300,6 +307,7 @@ pub async fn multi_search_with_post(
|
|||||||
include_metadata,
|
include_metadata,
|
||||||
},
|
},
|
||||||
&index,
|
&index,
|
||||||
|
&progress_clone,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@@ -314,6 +322,7 @@ pub async fn multi_search_with_post(
|
|||||||
personalize,
|
personalize,
|
||||||
personalize_query.as_deref(),
|
personalize_query.as_deref(),
|
||||||
time_budget,
|
time_budget,
|
||||||
|
&progress,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.with_index(query_index)?;
|
.with_index(query_index)?;
|
||||||
@@ -324,15 +333,19 @@ pub async fn multi_search_with_post(
|
|||||||
result: search_result,
|
result: search_result,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(search_results)
|
Ok(search_results)
|
||||||
}
|
}
|
||||||
.await;
|
.await;
|
||||||
permit.drop().await;
|
permit.drop().await;
|
||||||
|
|
||||||
|
let analytics_step =
|
||||||
|
progress.update_progress_scoped(TotalProcessingTimeStep::PublishingAnalytics);
|
||||||
if search_results.is_ok() {
|
if search_results.is_ok() {
|
||||||
multi_aggregate.succeed();
|
multi_aggregate.succeed();
|
||||||
}
|
}
|
||||||
analytics.publish(multi_aggregate, &req);
|
analytics.publish(multi_aggregate, &req);
|
||||||
|
drop(analytics_step);
|
||||||
|
|
||||||
let search_results = search_results.map_err(|(mut err, query_index)| {
|
let search_results = search_results.map_err(|(mut err, query_index)| {
|
||||||
// Add the query index that failed as context for the error message.
|
// Add the query index that failed as context for the error message.
|
||||||
@@ -345,6 +358,7 @@ pub async fn multi_search_with_post(
|
|||||||
debug!(
|
debug!(
|
||||||
request_uid = ?request_uid,
|
request_uid = ?request_uid,
|
||||||
returns = ?search_results,
|
returns = ?search_results,
|
||||||
|
progress = ?progress.accumulated_durations(),
|
||||||
"Multi-search"
|
"Multi-search"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ use index_scheduler::{IndexScheduler, RoFeatures};
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use meilisearch_types::error::ResponseError;
|
use meilisearch_types::error::ResponseError;
|
||||||
use meilisearch_types::milli::order_by_map::OrderByMap;
|
use meilisearch_types::milli::order_by_map::OrderByMap;
|
||||||
|
use meilisearch_types::milli::progress::Progress;
|
||||||
use meilisearch_types::milli::score_details::{ScoreDetails, WeightedScoreValue};
|
use meilisearch_types::milli::score_details::{ScoreDetails, WeightedScoreValue};
|
||||||
use meilisearch_types::milli::vector::Embedding;
|
use meilisearch_types::milli::vector::Embedding;
|
||||||
use meilisearch_types::milli::{self, DocumentId, OrderBy, TimeBudget, DEFAULT_VALUES_PER_FACET};
|
use meilisearch_types::milli::{
|
||||||
|
self, DocumentId, FederatingResultsStep, OrderBy, SearchStep, TimeBudget,
|
||||||
|
DEFAULT_VALUES_PER_FACET,
|
||||||
|
};
|
||||||
use meilisearch_types::network::{Network, Remote};
|
use meilisearch_types::network::{Network, Remote};
|
||||||
use roaring::RoaringBitmap;
|
use roaring::RoaringBitmap;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
@@ -43,6 +47,7 @@ pub async fn perform_federated_search(
|
|||||||
is_proxy: bool,
|
is_proxy: bool,
|
||||||
request_uid: Uuid,
|
request_uid: Uuid,
|
||||||
include_metadata: bool,
|
include_metadata: bool,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<FederatedSearchResult, ResponseError> {
|
) -> Result<FederatedSearchResult, ResponseError> {
|
||||||
if is_proxy {
|
if is_proxy {
|
||||||
features.check_network("Performing a remote federated search")?;
|
features.check_network("Performing a remote federated search")?;
|
||||||
@@ -111,7 +116,7 @@ pub async fn perform_federated_search(
|
|||||||
|
|
||||||
for (index_uid, queries) in partitioned_queries.local_queries_by_index {
|
for (index_uid, queries) in partitioned_queries.local_queries_by_index {
|
||||||
// note: this is the only place we open `index_uid`
|
// note: this is the only place we open `index_uid`
|
||||||
search_by_index.execute(index_uid, queries, ¶ms)?;
|
search_by_index.execute(index_uid, queries, ¶ms, progress)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bonus step, make sure to return an error if an index wants a non-faceted field, even if no query actually uses that index.
|
// bonus step, make sure to return an error if an index wants a non-faceted field, even if no query actually uses that index.
|
||||||
@@ -126,6 +131,8 @@ pub async fn perform_federated_search(
|
|||||||
facet_order,
|
facet_order,
|
||||||
} = search_by_index;
|
} = search_by_index;
|
||||||
|
|
||||||
|
progress.update_progress(SearchStep::FederatingResults);
|
||||||
|
progress.update_progress(FederatingResultsStep::WaitingForRemoteResults);
|
||||||
let before_waiting_remote_results = std::time::Instant::now();
|
let before_waiting_remote_results = std::time::Instant::now();
|
||||||
|
|
||||||
// 2.3. Wait for proxy search requests to complete
|
// 2.3. Wait for proxy search requests to complete
|
||||||
@@ -134,7 +141,7 @@ pub async fn perform_federated_search(
|
|||||||
let after_waiting_remote_results = std::time::Instant::now();
|
let after_waiting_remote_results = std::time::Instant::now();
|
||||||
|
|
||||||
// 3. merge hits and metadata across indexes and hosts
|
// 3. merge hits and metadata across indexes and hosts
|
||||||
|
progress.update_progress(FederatingResultsStep::MergingResults);
|
||||||
// 3.1. Build metadata in the same order as the original queries
|
// 3.1. Build metadata in the same order as the original queries
|
||||||
let query_metadata = precomputed_query_metadata.map(|precomputed_query_metadata| {
|
let query_metadata = precomputed_query_metadata.map(|precomputed_query_metadata| {
|
||||||
// If a remote is present, set the local remote name
|
// If a remote is present, set the local remote name
|
||||||
@@ -187,6 +194,7 @@ pub async fn perform_federated_search(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 3.5. merge facets
|
// 3.5. merge facets
|
||||||
|
progress.update_progress(FederatingResultsStep::MergingFacets);
|
||||||
let (facet_distribution, facet_stats, facets_by_index) =
|
let (facet_distribution, facet_stats, facets_by_index) =
|
||||||
facet_order.merge(federation.merge_facets, remote_results, facets);
|
facet_order.merge(federation.merge_facets, remote_results, facets);
|
||||||
|
|
||||||
@@ -831,6 +839,7 @@ impl SearchByIndex {
|
|||||||
index_uid: String,
|
index_uid: String,
|
||||||
queries: Vec<QueryByIndex>,
|
queries: Vec<QueryByIndex>,
|
||||||
params: &SearchByIndexParams<'_>,
|
params: &SearchByIndexParams<'_>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<(), ResponseError> {
|
) -> Result<(), ResponseError> {
|
||||||
let first_query_index = queries.first().map(|query| query.query_index);
|
let first_query_index = queries.first().map(|query| query.query_index);
|
||||||
let index = match params.index_scheduler.index(&index_uid) {
|
let index = match params.index_scheduler.index(&index_uid) {
|
||||||
@@ -957,6 +966,7 @@ impl SearchByIndex {
|
|||||||
// clones of `TimeBudget` share the budget rather than restart it
|
// clones of `TimeBudget` share the budget rather than restart it
|
||||||
time_budget.clone(),
|
time_budget.clone(),
|
||||||
params.features,
|
params.features,
|
||||||
|
progress,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
search.scoring_strategy(milli::score_details::ScoringStrategy::Detailed);
|
search.scoring_strategy(milli::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -1044,7 +1054,7 @@ impl SearchByIndex {
|
|||||||
hit_maker,
|
hit_maker,
|
||||||
query_index,
|
query_index,
|
||||||
}| {
|
}| {
|
||||||
let mut hit = hit_maker.make_hit(docid, &score)?;
|
let mut hit = hit_maker.make_hit(docid, &score, progress)?;
|
||||||
let weighted_score = ScoreDetails::global_score(score.iter()) * (*weight);
|
let weighted_score = ScoreDetails::global_score(score.iter()) * (*weight);
|
||||||
|
|
||||||
let mut _federation = serde_json::json!(
|
let mut _federation = serde_json::json!(
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ use meilisearch_types::heed::RoTxn;
|
|||||||
use meilisearch_types::index_uid::IndexUid;
|
use meilisearch_types::index_uid::IndexUid;
|
||||||
use meilisearch_types::locales::Locale;
|
use meilisearch_types::locales::Locale;
|
||||||
use meilisearch_types::milli::index::{self, EmbeddingsWithMetadata, SearchParameters};
|
use meilisearch_types::milli::index::{self, EmbeddingsWithMetadata, SearchParameters};
|
||||||
|
use meilisearch_types::milli::progress::Progress;
|
||||||
use meilisearch_types::milli::score_details::{ScoreDetails, ScoringStrategy};
|
use meilisearch_types::milli::score_details::{ScoreDetails, ScoringStrategy};
|
||||||
use meilisearch_types::milli::vector::parsed_vectors::ExplicitVectors;
|
use meilisearch_types::milli::vector::parsed_vectors::ExplicitVectors;
|
||||||
use meilisearch_types::milli::vector::Embedder;
|
use meilisearch_types::milli::vector::Embedder;
|
||||||
use meilisearch_types::milli::{
|
use meilisearch_types::milli::{
|
||||||
FacetValueHit, InternalError, OrderBy, PatternMatch, SearchForFacetValues, TimeBudget,
|
FacetValueHit, InternalError, OrderBy, PatternMatch, SearchForFacetValues, SearchStep,
|
||||||
|
TimeBudget,
|
||||||
};
|
};
|
||||||
use meilisearch_types::settings::DEFAULT_PAGINATION_MAX_TOTAL_HITS;
|
use meilisearch_types::settings::DEFAULT_PAGINATION_MAX_TOTAL_HITS;
|
||||||
use meilisearch_types::{milli, Document};
|
use meilisearch_types::{milli, Document};
|
||||||
@@ -1024,11 +1026,13 @@ pub fn prepare_search<'t>(
|
|||||||
search_kind: &SearchKind,
|
search_kind: &SearchKind,
|
||||||
time_budget: TimeBudget,
|
time_budget: TimeBudget,
|
||||||
features: RoFeatures,
|
features: RoFeatures,
|
||||||
|
progress: &'t Progress,
|
||||||
) -> Result<(milli::Search<'t>, bool, usize, usize), ResponseError> {
|
) -> Result<(milli::Search<'t>, bool, usize, usize), ResponseError> {
|
||||||
|
let _step = progress.update_progress_scoped(SearchStep::PreparingSearch);
|
||||||
if query.media.is_some() {
|
if query.media.is_some() {
|
||||||
features.check_multimodal("passing `media` in a search query")?;
|
features.check_multimodal("passing `media` in a search query")?;
|
||||||
}
|
}
|
||||||
let mut search = index.search(rtxn);
|
let mut search = index.search(rtxn, progress);
|
||||||
search.time_budget(time_budget);
|
search.time_budget(time_budget);
|
||||||
if let Some(ranking_score_threshold) = query.ranking_score_threshold {
|
if let Some(ranking_score_threshold) = query.ranking_score_threshold {
|
||||||
search.ranking_score_threshold(ranking_score_threshold.0);
|
search.ranking_score_threshold(ranking_score_threshold.0);
|
||||||
@@ -1048,6 +1052,7 @@ pub fn prepare_search<'t>(
|
|||||||
let vector = match query.vector.clone() {
|
let vector = match query.vector.clone() {
|
||||||
Some(vector) => vector,
|
Some(vector) => vector,
|
||||||
None => {
|
None => {
|
||||||
|
let _ = progress.update_progress_scoped(SearchStep::EmbeddingQuery);
|
||||||
let span = tracing::trace_span!(target: "search::vector", "embed_one");
|
let span = tracing::trace_span!(target: "search::vector", "embed_one");
|
||||||
let _entered = span.enter();
|
let _entered = span.enter();
|
||||||
|
|
||||||
@@ -1061,6 +1066,7 @@ pub fn prepare_search<'t>(
|
|||||||
(q, media) => milli::vector::SearchQuery::Media { q, media },
|
(q, media) => milli::vector::SearchQuery::Media { q, media },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
embedder
|
embedder
|
||||||
.embed_search(search_query, Some(deadline))
|
.embed_search(search_query, Some(deadline))
|
||||||
.map_err(milli::vector::Error::from)
|
.map_err(milli::vector::Error::from)
|
||||||
@@ -1173,6 +1179,7 @@ pub struct SearchParams {
|
|||||||
pub fn perform_search(
|
pub fn perform_search(
|
||||||
params: SearchParams,
|
params: SearchParams,
|
||||||
index: &Index,
|
index: &Index,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<(SearchResult, TimeBudget), ResponseError> {
|
) -> Result<(SearchResult, TimeBudget), ResponseError> {
|
||||||
let SearchParams {
|
let SearchParams {
|
||||||
index_uid,
|
index_uid,
|
||||||
@@ -1191,8 +1198,15 @@ pub fn perform_search(
|
|||||||
None => TimeBudget::default(),
|
None => TimeBudget::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (search, is_finite_pagination, max_total_hits, offset) =
|
let (search, is_finite_pagination, max_total_hits, offset) = prepare_search(
|
||||||
prepare_search(index, &rtxn, &query, &search_kind, time_budget.clone(), features)?;
|
index,
|
||||||
|
&rtxn,
|
||||||
|
&query,
|
||||||
|
&search_kind,
|
||||||
|
time_budget.clone(),
|
||||||
|
features,
|
||||||
|
progress,
|
||||||
|
)?;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
milli::SearchResult {
|
milli::SearchResult {
|
||||||
@@ -1253,6 +1267,7 @@ pub fn perform_search(
|
|||||||
personalize: _,
|
personalize: _,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
|
progress.update_progress(SearchStep::FormattingResults);
|
||||||
let format = AttributesFormat {
|
let format = AttributesFormat {
|
||||||
attributes_to_retrieve,
|
attributes_to_retrieve,
|
||||||
retrieve_vectors,
|
retrieve_vectors,
|
||||||
@@ -1275,6 +1290,7 @@ pub fn perform_search(
|
|||||||
format,
|
format,
|
||||||
matching_words,
|
matching_words,
|
||||||
documents_ids.iter().copied().zip(document_scores.iter()),
|
documents_ids.iter().copied().zip(document_scores.iter()),
|
||||||
|
progress,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let number_of_hits = min(candidates.len() as usize, max_total_hits);
|
let number_of_hits = min(candidates.len() as usize, max_total_hits);
|
||||||
@@ -1297,11 +1313,13 @@ pub fn perform_search(
|
|||||||
|
|
||||||
let (facet_distribution, facet_stats) = facets
|
let (facet_distribution, facet_stats) = facets
|
||||||
.map(move |facets| {
|
.map(move |facets| {
|
||||||
|
let _ = progress.update_progress_scoped(SearchStep::ComputingFacetDistribution);
|
||||||
compute_facet_distribution_stats(&facets, index, &rtxn, candidates, Route::Search)
|
compute_facet_distribution_stats(&facets, index, &rtxn, candidates, Route::Search)
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.map(|ComputedFacets { distribution, stats }| (distribution, stats))
|
.map(|ComputedFacets { distribution, stats }| (distribution, stats))
|
||||||
.unzip();
|
.unzip();
|
||||||
|
|
||||||
let result = SearchResult {
|
let result = SearchResult {
|
||||||
hits: documents,
|
hits: documents,
|
||||||
hits_info,
|
hits_info,
|
||||||
@@ -1316,6 +1334,7 @@ pub fn perform_search(
|
|||||||
request_uid: Some(request_uid),
|
request_uid: Some(request_uid),
|
||||||
metadata,
|
metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((result, time_budget))
|
Ok((result, time_budget))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1580,7 +1599,13 @@ impl<'a> HitMaker<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_hit(&self, id: u32, score: &[ScoreDetails]) -> milli::Result<SearchHit> {
|
pub fn make_hit(
|
||||||
|
&self,
|
||||||
|
id: u32,
|
||||||
|
score: &[ScoreDetails],
|
||||||
|
progress: &Progress,
|
||||||
|
) -> milli::Result<SearchHit> {
|
||||||
|
let _step = progress.update_progress_scoped(SearchStep::FormattingResults);
|
||||||
let (_, obkv) =
|
let (_, obkv) =
|
||||||
self.index.iter_documents(self.rtxn, std::iter::once(id))?.next().unwrap()?;
|
self.index.iter_documents(self.rtxn, std::iter::once(id))?.next().unwrap()?;
|
||||||
|
|
||||||
@@ -1669,6 +1694,7 @@ fn make_hits<'a>(
|
|||||||
format: AttributesFormat,
|
format: AttributesFormat,
|
||||||
matching_words: milli::MatchingWords,
|
matching_words: milli::MatchingWords,
|
||||||
documents_ids_scores: impl Iterator<Item = (u32, &'a Vec<ScoreDetails>)> + 'a,
|
documents_ids_scores: impl Iterator<Item = (u32, &'a Vec<ScoreDetails>)> + 'a,
|
||||||
|
progress: &Progress,
|
||||||
) -> milli::Result<Vec<SearchHit>> {
|
) -> milli::Result<Vec<SearchHit>> {
|
||||||
let mut documents = Vec::new();
|
let mut documents = Vec::new();
|
||||||
|
|
||||||
@@ -1686,7 +1712,7 @@ fn make_hits<'a>(
|
|||||||
let hit_maker = HitMaker::new(index, rtxn, format, formatter_builder)?;
|
let hit_maker = HitMaker::new(index, rtxn, format, formatter_builder)?;
|
||||||
|
|
||||||
for (id, score) in documents_ids_scores {
|
for (id, score) in documents_ids_scores {
|
||||||
documents.push(hit_maker.make_hit(id, score)?);
|
documents.push(hit_maker.make_hit(id, score, progress)?);
|
||||||
}
|
}
|
||||||
Ok(documents)
|
Ok(documents)
|
||||||
}
|
}
|
||||||
@@ -1701,6 +1727,7 @@ pub fn perform_facet_search(
|
|||||||
locales: Option<Vec<Language>>,
|
locales: Option<Vec<Language>>,
|
||||||
) -> Result<FacetSearchResult, ResponseError> {
|
) -> Result<FacetSearchResult, ResponseError> {
|
||||||
let before_search = Instant::now();
|
let before_search = Instant::now();
|
||||||
|
let progress = Progress::default();
|
||||||
let rtxn = index.read_txn()?;
|
let rtxn = index.read_txn()?;
|
||||||
let time_budget = match index.search_cutoff(&rtxn)? {
|
let time_budget = match index.search_cutoff(&rtxn)? {
|
||||||
Some(cutoff) => TimeBudget::new(Duration::from_millis(cutoff)),
|
Some(cutoff) => TimeBudget::new(Duration::from_millis(cutoff)),
|
||||||
@@ -1729,8 +1756,15 @@ pub fn perform_facet_search(
|
|||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
let (search, _, _, _) =
|
let (search, _, _, _) = prepare_search(
|
||||||
prepare_search(index, &rtxn, &search_query, &search_kind, time_budget, features)?;
|
index,
|
||||||
|
&rtxn,
|
||||||
|
&search_query,
|
||||||
|
&search_kind,
|
||||||
|
time_budget,
|
||||||
|
features,
|
||||||
|
&progress,
|
||||||
|
)?;
|
||||||
let mut facet_search = SearchForFacetValues::new(
|
let mut facet_search = SearchForFacetValues::new(
|
||||||
facet_name,
|
facet_name,
|
||||||
search,
|
search,
|
||||||
@@ -1762,6 +1796,7 @@ pub fn perform_similar(
|
|||||||
quantized: bool,
|
quantized: bool,
|
||||||
retrieve_vectors: RetrieveVectors,
|
retrieve_vectors: RetrieveVectors,
|
||||||
features: RoFeatures,
|
features: RoFeatures,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<SimilarResult, ResponseError> {
|
) -> Result<SimilarResult, ResponseError> {
|
||||||
let before_search = Instant::now();
|
let before_search = Instant::now();
|
||||||
let rtxn = index.read_txn()?;
|
let rtxn = index.read_txn()?;
|
||||||
@@ -1851,6 +1886,7 @@ pub fn perform_similar(
|
|||||||
format,
|
format,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
documents_ids.iter().copied().zip(document_scores.iter()),
|
documents_ids.iter().copied().zip(document_scores.iter()),
|
||||||
|
progress,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let max_total_hits = index
|
let max_total_hits = index
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use crate::heed_codec::facet::{
|
|||||||
use crate::heed_codec::version::VersionCodec;
|
use crate::heed_codec::version::VersionCodec;
|
||||||
use crate::heed_codec::{BEU16StrCodec, FstSetCodec, StrBEU16Codec, StrRefCodec};
|
use crate::heed_codec::{BEU16StrCodec, FstSetCodec, StrBEU16Codec, StrRefCodec};
|
||||||
use crate::order_by_map::OrderByMap;
|
use crate::order_by_map::OrderByMap;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::prompt::PromptData;
|
use crate::prompt::PromptData;
|
||||||
use crate::proximity::ProximityPrecision;
|
use crate::proximity::ProximityPrecision;
|
||||||
use crate::update::new::StdResult;
|
use crate::update::new::StdResult;
|
||||||
@@ -599,6 +600,13 @@ impl Index {
|
|||||||
/// Returns the fields ids map which associate the documents keys with an internal field id
|
/// Returns the fields ids map which associate the documents keys with an internal field id
|
||||||
/// (i.e. `u8`), this field id is used to identify fields in the obkv documents.
|
/// (i.e. `u8`), this field id is used to identify fields in the obkv documents.
|
||||||
pub fn fields_ids_map(&self, rtxn: &RoTxn<'_>) -> heed::Result<FieldsIdsMap> {
|
pub fn fields_ids_map(&self, rtxn: &RoTxn<'_>) -> heed::Result<FieldsIdsMap> {
|
||||||
|
let map = self.fields_ids_map_with_metadata(rtxn).unwrap();
|
||||||
|
eprintln!(
|
||||||
|
"fields_ids_map: {:?}",
|
||||||
|
map.iter_id_metadata()
|
||||||
|
.map(|(id, metadata)| (id, map.name(id).unwrap(), metadata))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
);
|
||||||
Ok(self
|
Ok(self
|
||||||
.main
|
.main
|
||||||
.remap_types::<Str, SerdeJson<FieldsIdsMap>>()
|
.remap_types::<Str, SerdeJson<FieldsIdsMap>>()
|
||||||
@@ -611,7 +619,10 @@ impl Index {
|
|||||||
/// This structure is not yet stored in the index, and is generated on the fly.
|
/// This structure is not yet stored in the index, and is generated on the fly.
|
||||||
pub fn fields_ids_map_with_metadata(&self, rtxn: &RoTxn<'_>) -> Result<FieldIdMapWithMetadata> {
|
pub fn fields_ids_map_with_metadata(&self, rtxn: &RoTxn<'_>) -> Result<FieldIdMapWithMetadata> {
|
||||||
Ok(FieldIdMapWithMetadata::new(
|
Ok(FieldIdMapWithMetadata::new(
|
||||||
self.fields_ids_map(rtxn)?,
|
self.main
|
||||||
|
.remap_types::<Str, SerdeJson<FieldsIdsMap>>()
|
||||||
|
.get(rtxn, main_key::FIELDS_IDS_MAP_KEY)?
|
||||||
|
.unwrap_or_default(),
|
||||||
MetadataBuilder::from_index(self, rtxn)?,
|
MetadataBuilder::from_index(self, rtxn)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -1477,8 +1488,8 @@ impl Index {
|
|||||||
FacetDistribution::new(rtxn, self)
|
FacetDistribution::new(rtxn, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search<'a>(&'a self, rtxn: &'a RoTxn<'a>) -> Search<'a> {
|
pub fn search<'a>(&'a self, rtxn: &'a RoTxn<'a>, progress: &'a Progress) -> Search<'a> {
|
||||||
Search::new(rtxn, self)
|
Search::new(rtxn, self, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the index creation time.
|
/// Returns the index creation time.
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ pub use self::index::Index;
|
|||||||
pub use self::localized_attributes_rules::LocalizedAttributesRule;
|
pub use self::localized_attributes_rules::LocalizedAttributesRule;
|
||||||
pub use self::search::facet::{FacetValueHit, SearchForFacetValues};
|
pub use self::search::facet::{FacetValueHit, SearchForFacetValues};
|
||||||
pub use self::search::similar::Similar;
|
pub use self::search::similar::Similar;
|
||||||
|
pub use self::search::steps::{FederatingResultsStep, SearchStep, TotalProcessingTimeStep};
|
||||||
pub use self::search::{
|
pub use self::search::{
|
||||||
FacetDistribution, Filter, FormatOptions, MatchBounds, MatcherBuilder, MatchingWords, OrderBy,
|
FacetDistribution, Filter, FormatOptions, MatchBounds, MatcherBuilder, MatchingWords, OrderBy,
|
||||||
Search, SearchResult, SemanticSearch, TermsMatchingStrategy, DEFAULT_VALUES_PER_FACET,
|
Search, SearchResult, SemanticSearch, TermsMatchingStrategy, DEFAULT_VALUES_PER_FACET,
|
||||||
|
|||||||
@@ -64,6 +64,30 @@ impl Progress {
|
|||||||
steps.push((step_type, Box::new(sub_progress), now));
|
steps.push((step_type, Box::new(sub_progress), now));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// End a step that has been started without having to start a new step.
|
||||||
|
fn end_progress_step<P: Step>(&self, sub_progress: P) {
|
||||||
|
let mut inner = self.steps.write().unwrap();
|
||||||
|
let InnerProgress { steps, durations } = &mut *inner;
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
let step_type = TypeId::of::<P>();
|
||||||
|
debug_assert!(
|
||||||
|
steps.iter().any(|(id, s, _)| *id == step_type && s.name() == sub_progress.name()),
|
||||||
|
"Step `{}` must have been started",
|
||||||
|
sub_progress.name()
|
||||||
|
);
|
||||||
|
if let Some(idx) = steps.iter().position(|(id, _, _)| *id == step_type) {
|
||||||
|
push_steps_durations(steps, durations, now, idx);
|
||||||
|
steps.truncate(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the progress and return a scoped progress step that will end the progress step when dropped.
|
||||||
|
pub fn update_progress_scoped<P: Step + Copy>(&self, step: P) -> ScopedProgressStep<'_, P> {
|
||||||
|
self.update_progress(step);
|
||||||
|
ScopedProgressStep { progress: self, step }
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This code should be in meilisearch_types but cannot because milli can't depend on meilisearch_types
|
// TODO: This code should be in meilisearch_types but cannot because milli can't depend on meilisearch_types
|
||||||
pub fn as_progress_view(&self) -> ProgressView {
|
pub fn as_progress_view(&self) -> ProgressView {
|
||||||
let inner = self.steps.read().unwrap();
|
let inner = self.steps.read().unwrap();
|
||||||
@@ -95,7 +119,15 @@ impl Progress {
|
|||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
push_steps_durations(steps, &mut durations, now, 0);
|
push_steps_durations(steps, &mut durations, now, 0);
|
||||||
|
|
||||||
durations.drain(..).map(|(name, duration)| (name, format!("{duration:.2?}"))).collect()
|
let mut accumulated_durations = IndexMap::new();
|
||||||
|
for (name, duration) in durations.drain(..) {
|
||||||
|
accumulated_durations.entry(name).and_modify(|d| *d += duration).or_insert(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulated_durations
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, duration)| (name, format!("{duration:.2?}")))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ideally we should expose the progress in a way that let arroy use it directly
|
// TODO: ideally we should expose the progress in a way that let arroy use it directly
|
||||||
@@ -343,3 +375,14 @@ impl<T: steppe::Step> Step for Compat<T> {
|
|||||||
self.0.total().try_into().unwrap_or(u32::MAX)
|
self.0.total().try_into().unwrap_or(u32::MAX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ScopedProgressStep<'a, P: Step + Copy> {
|
||||||
|
progress: &'a Progress,
|
||||||
|
step: P,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Step + Copy> Drop for ScopedProgressStep<'a, P> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.progress.end_progress_step(self.step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1165,7 +1165,7 @@ mod tests {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
// 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(Filter::from_str("monitor_diagonal = '27\" to 30\\''").unwrap().unwrap());
|
search.filter(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();
|
||||||
@@ -1225,7 +1225,7 @@ mod tests {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
|
|
||||||
search.filter(Filter::from_str("_geoRadius(45.4777599, 9.1967508, 0)").unwrap().unwrap());
|
search.filter(Filter::from_str("_geoRadius(45.4777599, 9.1967508, 0)").unwrap().unwrap());
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use roaring::RoaringBitmap;
|
|||||||
|
|
||||||
use crate::score_details::{ScoreDetails, ScoreValue, ScoringStrategy};
|
use crate::score_details::{ScoreDetails, ScoreValue, ScoringStrategy};
|
||||||
use crate::search::new::{distinct_fid, distinct_single_docid};
|
use crate::search::new::{distinct_fid, distinct_single_docid};
|
||||||
|
use crate::search::steps::SearchStep;
|
||||||
use crate::search::SemanticSearch;
|
use crate::search::SemanticSearch;
|
||||||
use crate::vector::{Embedding, SearchQuery};
|
use crate::vector::{Embedding, SearchQuery};
|
||||||
use crate::{Index, MatchingWords, Result, Search, SearchResult};
|
use crate::{Index, MatchingWords, Result, Search, SearchResult};
|
||||||
@@ -221,6 +222,7 @@ impl Search<'_> {
|
|||||||
time_budget: self.time_budget.clone(),
|
time_budget: self.time_budget.clone(),
|
||||||
ranking_score_threshold: self.ranking_score_threshold,
|
ranking_score_threshold: self.ranking_score_threshold,
|
||||||
locales: self.locales.clone(),
|
locales: self.locales.clone(),
|
||||||
|
progress: self.progress,
|
||||||
};
|
};
|
||||||
|
|
||||||
let semantic = search.semantic.take();
|
let semantic = search.semantic.take();
|
||||||
@@ -241,6 +243,7 @@ impl Search<'_> {
|
|||||||
Some(vector_query) => vector_query,
|
Some(vector_query) => vector_query,
|
||||||
None => {
|
None => {
|
||||||
// attempt to embed the vector
|
// attempt to embed the vector
|
||||||
|
self.progress.update_progress(SearchStep::EmbeddingQuery);
|
||||||
let span = tracing::trace_span!(target: "search::hybrid", "embed_one");
|
let span = tracing::trace_span!(target: "search::hybrid", "embed_one");
|
||||||
let _entered = span.enter();
|
let _entered = span.enter();
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ use self::new::{execute_vector_search, PartialSearchResult, VectorStoreStats};
|
|||||||
use crate::documents::GeoSortParameter;
|
use crate::documents::GeoSortParameter;
|
||||||
use crate::filterable_attributes_rules::{filtered_matching_patterns, matching_features};
|
use crate::filterable_attributes_rules::{filtered_matching_patterns, matching_features};
|
||||||
use crate::index::MatchingStrategy;
|
use crate::index::MatchingStrategy;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
||||||
|
use crate::search::steps::SearchStep;
|
||||||
use crate::vector::{Embedder, Embedding};
|
use crate::vector::{Embedder, Embedding};
|
||||||
use crate::{
|
use crate::{
|
||||||
execute_search, filtered_universe, AscDesc, DefaultSearchLogger, DocumentId, Error, Index,
|
execute_search, filtered_universe, AscDesc, DefaultSearchLogger, DocumentId, Error, Index,
|
||||||
@@ -29,6 +31,7 @@ mod fst_utils;
|
|||||||
pub mod hybrid;
|
pub mod hybrid;
|
||||||
pub mod new;
|
pub mod new;
|
||||||
pub mod similar;
|
pub mod similar;
|
||||||
|
pub mod steps;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SemanticSearch {
|
pub struct SemanticSearch {
|
||||||
@@ -61,10 +64,11 @@ pub struct Search<'a> {
|
|||||||
time_budget: TimeBudget,
|
time_budget: TimeBudget,
|
||||||
ranking_score_threshold: Option<f64>,
|
ranking_score_threshold: Option<f64>,
|
||||||
locales: Option<Vec<Language>>,
|
locales: Option<Vec<Language>>,
|
||||||
|
progress: &'a Progress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Search<'a> {
|
impl<'a> Search<'a> {
|
||||||
pub fn new(rtxn: &'a heed::RoTxn<'a>, index: &'a Index) -> Search<'a> {
|
pub fn new(rtxn: &'a heed::RoTxn<'a>, index: &'a Index, progress: &'a Progress) -> Search<'a> {
|
||||||
Search {
|
Search {
|
||||||
query: None,
|
query: None,
|
||||||
filter: None,
|
filter: None,
|
||||||
@@ -86,6 +90,7 @@ impl<'a> Search<'a> {
|
|||||||
locales: None,
|
locales: None,
|
||||||
time_budget: TimeBudget::max(),
|
time_budget: TimeBudget::max(),
|
||||||
ranking_score_threshold: None,
|
ranking_score_threshold: None,
|
||||||
|
progress,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +203,7 @@ impl<'a> Search<'a> {
|
|||||||
pub fn execute_for_candidates(&self, has_vector_search: bool) -> Result<RoaringBitmap> {
|
pub fn execute_for_candidates(&self, has_vector_search: bool) -> Result<RoaringBitmap> {
|
||||||
if has_vector_search {
|
if has_vector_search {
|
||||||
let ctx = SearchContext::new(self.index, self.rtxn)?;
|
let ctx = SearchContext::new(self.index, self.rtxn)?;
|
||||||
filtered_universe(ctx.index, ctx.txn, &self.filter)
|
filtered_universe(ctx.index, ctx.txn, &self.filter, self.progress)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.execute()?.candidates)
|
Ok(self.execute()?.candidates)
|
||||||
}
|
}
|
||||||
@@ -239,8 +244,9 @@ impl<'a> Search<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let universe = filtered_universe(ctx.index, ctx.txn, &self.filter)?;
|
let universe = filtered_universe(ctx.index, ctx.txn, &self.filter, self.progress)?;
|
||||||
let mut query_vector = None;
|
let mut query_vector = None;
|
||||||
|
|
||||||
let PartialSearchResult {
|
let PartialSearchResult {
|
||||||
located_query_terms,
|
located_query_terms,
|
||||||
candidates,
|
candidates,
|
||||||
@@ -276,6 +282,7 @@ impl<'a> Search<'a> {
|
|||||||
*quantized,
|
*quantized,
|
||||||
self.time_budget.clone(),
|
self.time_budget.clone(),
|
||||||
self.ranking_score_threshold,
|
self.ranking_score_threshold,
|
||||||
|
self.progress,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
_ => execute_search(
|
_ => execute_search(
|
||||||
@@ -297,6 +304,7 @@ impl<'a> Search<'a> {
|
|||||||
self.time_budget.clone(),
|
self.time_budget.clone(),
|
||||||
self.ranking_score_threshold,
|
self.ranking_score_threshold,
|
||||||
self.locales.as_ref(),
|
self.locales.as_ref(),
|
||||||
|
self.progress,
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,6 +314,7 @@ impl<'a> Search<'a> {
|
|||||||
tracing::debug!("Vector store stats: total_time={total_time:.02?}, total_queries={total_queries}, total_results={total_results}");
|
tracing::debug!("Vector store stats: total_time={total_time:.02?}, total_queries={total_queries}, total_results={total_results}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.progress.update_progress(SearchStep::FormattingResults);
|
||||||
// consume context and located_query_terms to build MatchingWords.
|
// consume context and located_query_terms to build MatchingWords.
|
||||||
let matching_words = match located_query_terms {
|
let matching_words = match located_query_terms {
|
||||||
Some(located_query_terms) => MatchingWords::new(ctx, located_query_terms),
|
Some(located_query_terms) => MatchingWords::new(ctx, located_query_terms),
|
||||||
@@ -347,6 +356,7 @@ impl fmt::Debug for Search<'_> {
|
|||||||
time_budget,
|
time_budget,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
|
progress: _,
|
||||||
} = self;
|
} = self;
|
||||||
f.debug_struct("Search")
|
f.debug_struct("Search")
|
||||||
.field("query", query)
|
.field("query", query)
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ use roaring::RoaringBitmap;
|
|||||||
use super::logger::SearchLogger;
|
use super::logger::SearchLogger;
|
||||||
use super::ranking_rules::{BoxRankingRule, RankingRuleQueryTrait};
|
use super::ranking_rules::{BoxRankingRule, RankingRuleQueryTrait};
|
||||||
use super::SearchContext;
|
use super::SearchContext;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
||||||
use crate::search::new::distinct::{
|
use crate::search::new::distinct::{
|
||||||
apply_distinct_rule, distinct_fid, distinct_single_docid, DistinctOutput,
|
apply_distinct_rule, distinct_fid, distinct_single_docid, DistinctOutput,
|
||||||
};
|
};
|
||||||
|
use crate::search::steps::{ComputingBucketSortStep, SearchStep};
|
||||||
use crate::{Result, TimeBudget};
|
use crate::{Result, TimeBudget};
|
||||||
|
|
||||||
pub struct BucketSortOutput {
|
pub struct BucketSortOutput {
|
||||||
@@ -34,7 +36,9 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
ranking_score_threshold: Option<f64>,
|
ranking_score_threshold: Option<f64>,
|
||||||
exhaustive_number_hits: bool,
|
exhaustive_number_hits: bool,
|
||||||
max_total_hits: Option<usize>,
|
max_total_hits: Option<usize>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<BucketSortOutput> {
|
) -> Result<BucketSortOutput> {
|
||||||
|
let _step = progress.update_progress_scoped(SearchStep::ComputingBucketSort);
|
||||||
logger.initial_query(query);
|
logger.initial_query(query);
|
||||||
logger.ranking_rules(&ranking_rules);
|
logger.ranking_rules(&ranking_rules);
|
||||||
logger.initial_universe(universe);
|
logger.initial_universe(universe);
|
||||||
@@ -93,6 +97,7 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let step = progress.update_progress_scoped(ComputingBucketSortStep::Initializing);
|
||||||
let ranking_rules_len = ranking_rules.len();
|
let ranking_rules_len = ranking_rules.len();
|
||||||
|
|
||||||
logger.start_iteration_ranking_rule(0, ranking_rules[0].as_ref(), query, universe);
|
logger.start_iteration_ranking_rule(0, ranking_rules[0].as_ref(), query, universe);
|
||||||
@@ -105,6 +110,7 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
vec![RoaringBitmap::default(); ranking_rules_len];
|
vec![RoaringBitmap::default(); ranking_rules_len];
|
||||||
ranking_rule_universes[0].clone_from(universe);
|
ranking_rule_universes[0].clone_from(universe);
|
||||||
let mut cur_ranking_rule_index = 0;
|
let mut cur_ranking_rule_index = 0;
|
||||||
|
drop(step);
|
||||||
|
|
||||||
/// Finish iterating over the current ranking rule, yielding
|
/// Finish iterating over the current ranking rule, yielding
|
||||||
/// control to the parent (or finishing the search if not possible).
|
/// control to the parent (or finishing the search if not possible).
|
||||||
@@ -157,6 +163,7 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
distinct_fid,
|
distinct_fid,
|
||||||
&ranking_rule_scores,
|
&ranking_rule_scores,
|
||||||
$candidates,
|
$candidates,
|
||||||
|
progress,
|
||||||
)?;
|
)?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -185,6 +192,7 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
ctx,
|
ctx,
|
||||||
logger,
|
logger,
|
||||||
&ranking_rule_universes[cur_ranking_rule_index],
|
&ranking_rule_universes[cur_ranking_rule_index],
|
||||||
|
progress,
|
||||||
)? {
|
)? {
|
||||||
std::task::Poll::Ready(bucket) => bucket,
|
std::task::Poll::Ready(bucket) => bucket,
|
||||||
std::task::Poll::Pending => {
|
std::task::Poll::Pending => {
|
||||||
@@ -231,6 +239,7 @@ pub fn bucket_sort<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
logger,
|
logger,
|
||||||
&ranking_rule_universes[cur_ranking_rule_index],
|
&ranking_rule_universes[cur_ranking_rule_index],
|
||||||
&time_budget,
|
&time_budget,
|
||||||
|
progress,
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
back!();
|
back!();
|
||||||
@@ -323,9 +332,11 @@ fn maybe_add_to_results<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
distinct_fid: Option<u16>,
|
distinct_fid: Option<u16>,
|
||||||
ranking_rule_scores: &[ScoreDetails],
|
ranking_rule_scores: &[ScoreDetails],
|
||||||
candidates: RoaringBitmap,
|
candidates: RoaringBitmap,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// First apply the distinct rule on the candidates, reducing the universes if necessary
|
// First apply the distinct rule on the candidates, reducing the universes if necessary
|
||||||
let candidates = if let Some(distinct_fid) = distinct_fid {
|
let candidates = if let Some(distinct_fid) = distinct_fid {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::ApplyingDistinctRule);
|
||||||
let DistinctOutput { remaining, excluded } =
|
let DistinctOutput { remaining, excluded } =
|
||||||
apply_distinct_rule(ctx, distinct_fid, &candidates)?;
|
apply_distinct_rule(ctx, distinct_fid, &candidates)?;
|
||||||
for universe in ranking_rule_universes.iter_mut() {
|
for universe in ranking_rule_universes.iter_mut() {
|
||||||
@@ -336,6 +347,8 @@ fn maybe_add_to_results<'ctx, Q: RankingRuleQueryTrait>(
|
|||||||
} else {
|
} else {
|
||||||
candidates.clone()
|
candidates.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
progress.update_progress(ComputingBucketSortStep::MergingCandidates);
|
||||||
*all_candidates |= &candidates;
|
*all_candidates |= &candidates;
|
||||||
|
|
||||||
// if the candidates are empty, there is nothing to do;
|
// if the candidates are empty, there is nothing to do;
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ use roaring::{MultiOps, RoaringBitmap};
|
|||||||
|
|
||||||
use super::query_graph::QueryGraph;
|
use super::query_graph::QueryGraph;
|
||||||
use super::ranking_rules::{RankingRule, RankingRuleOutput};
|
use super::ranking_rules::{RankingRule, RankingRuleOutput};
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{self, ScoreDetails};
|
use crate::score_details::{self, ScoreDetails};
|
||||||
use crate::search::new::query_graph::QueryNodeData;
|
use crate::search::new::query_graph::QueryNodeData;
|
||||||
use crate::search::new::query_term::ExactTerm;
|
use crate::search::new::query_term::ExactTerm;
|
||||||
|
use crate::search::new::ranking_rules::RankingRuleId;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::{CboRoaringBitmapCodec, Result, SearchContext, SearchLogger, TimeBudget};
|
use crate::{CboRoaringBitmapCodec, Result, SearchContext, SearchLogger, TimeBudget};
|
||||||
|
|
||||||
/// A ranking rule that produces 3 disjoint buckets:
|
/// A ranking rule that produces 3 disjoint buckets:
|
||||||
@@ -24,8 +27,8 @@ impl ExactAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> RankingRule<'ctx, QueryGraph> for ExactAttribute {
|
impl<'ctx> RankingRule<'ctx, QueryGraph> for ExactAttribute {
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> RankingRuleId {
|
||||||
"exact_attribute".to_owned()
|
RankingRuleId::Exactness
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, target = "search::exact_attribute")]
|
#[tracing::instrument(level = "trace", skip_all, target = "search::exact_attribute")]
|
||||||
@@ -48,7 +51,9 @@ impl<'ctx> RankingRule<'ctx, QueryGraph> for ExactAttribute {
|
|||||||
_logger: &mut dyn SearchLogger<QueryGraph>,
|
_logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
universe: &roaring::RoaringBitmap,
|
universe: &roaring::RoaringBitmap,
|
||||||
_time_budget: &TimeBudget,
|
_time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<QueryGraph>>> {
|
) -> Result<Option<RankingRuleOutput<QueryGraph>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
let state = std::mem::take(&mut self.state);
|
let state = std::mem::take(&mut self.state);
|
||||||
let (state, output) = State::next(state, universe);
|
let (state, output) = State::next(state, universe);
|
||||||
self.state = state;
|
self.state = state;
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use rstar::RTree;
|
|||||||
use super::ranking_rules::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait};
|
use super::ranking_rules::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait};
|
||||||
use crate::documents::geo_sort::{fill_cache, next_bucket};
|
use crate::documents::geo_sort::{fill_cache, next_bucket};
|
||||||
use crate::documents::{GeoSortParameter, GeoSortStrategy};
|
use crate::documents::{GeoSortParameter, GeoSortStrategy};
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{self, ScoreDetails};
|
use crate::score_details::{self, ScoreDetails};
|
||||||
|
use crate::search::new::ranking_rules::RankingRuleId;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::{GeoPoint, Result, SearchContext, SearchLogger, TimeBudget};
|
use crate::{GeoPoint, Result, SearchContext, SearchLogger, TimeBudget};
|
||||||
|
|
||||||
pub struct GeoSort<Q: RankingRuleQueryTrait> {
|
pub struct GeoSort<Q: RankingRuleQueryTrait> {
|
||||||
@@ -73,8 +76,8 @@ impl<Q: RankingRuleQueryTrait> GeoSort<Q> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for GeoSort<Q> {
|
impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for GeoSort<Q> {
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> RankingRuleId {
|
||||||
"geo_sort".to_owned()
|
RankingRuleId::GeoSort
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, target = "search::geo_sort")]
|
#[tracing::instrument(level = "trace", skip_all, target = "search::geo_sort")]
|
||||||
@@ -112,7 +115,9 @@ impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for GeoSort<Q> {
|
|||||||
_logger: &mut dyn SearchLogger<Q>,
|
_logger: &mut dyn SearchLogger<Q>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
_time_budget: &TimeBudget,
|
_time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<Q>>> {
|
) -> Result<Option<RankingRuleOutput<Q>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
let query = self.query.as_ref().unwrap().clone();
|
let query = self.query.as_ref().unwrap().clone();
|
||||||
|
|
||||||
next_bucket(
|
next_bucket(
|
||||||
|
|||||||
@@ -50,51 +50,54 @@ use super::ranking_rule_graph::{
|
|||||||
};
|
};
|
||||||
use super::small_bitmap::SmallBitmap;
|
use super::small_bitmap::SmallBitmap;
|
||||||
use super::{QueryGraph, RankingRule, RankingRuleOutput, SearchContext};
|
use super::{QueryGraph, RankingRule, RankingRuleOutput, SearchContext};
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::Rank;
|
use crate::score_details::Rank;
|
||||||
use crate::search::new::query_term::LocatedQueryTermSubset;
|
use crate::search::new::query_term::LocatedQueryTermSubset;
|
||||||
use crate::search::new::ranking_rule_graph::PathVisitor;
|
use crate::search::new::ranking_rule_graph::PathVisitor;
|
||||||
|
use crate::search::new::ranking_rules::RankingRuleId;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::{Result, TermsMatchingStrategy, TimeBudget};
|
use crate::{Result, TermsMatchingStrategy, TimeBudget};
|
||||||
|
|
||||||
pub type Words = GraphBasedRankingRule<WordsGraph>;
|
pub type Words = GraphBasedRankingRule<WordsGraph>;
|
||||||
impl GraphBasedRankingRule<WordsGraph> {
|
impl GraphBasedRankingRule<WordsGraph> {
|
||||||
pub fn new(terms_matching_strategy: TermsMatchingStrategy) -> Self {
|
pub fn new(terms_matching_strategy: TermsMatchingStrategy) -> Self {
|
||||||
Self::new_with_id("words".to_owned(), Some(terms_matching_strategy))
|
Self::new_with_id(RankingRuleId::Words, Some(terms_matching_strategy))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Proximity = GraphBasedRankingRule<ProximityGraph>;
|
pub type Proximity = GraphBasedRankingRule<ProximityGraph>;
|
||||||
impl GraphBasedRankingRule<ProximityGraph> {
|
impl GraphBasedRankingRule<ProximityGraph> {
|
||||||
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
||||||
Self::new_with_id("proximity".to_owned(), terms_matching_strategy)
|
Self::new_with_id(RankingRuleId::Proximity, terms_matching_strategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Fid = GraphBasedRankingRule<FidGraph>;
|
pub type Fid = GraphBasedRankingRule<FidGraph>;
|
||||||
impl GraphBasedRankingRule<FidGraph> {
|
impl GraphBasedRankingRule<FidGraph> {
|
||||||
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
||||||
Self::new_with_id("fid".to_owned(), terms_matching_strategy)
|
Self::new_with_id(RankingRuleId::AttributePosition, terms_matching_strategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Position = GraphBasedRankingRule<PositionGraph>;
|
pub type Position = GraphBasedRankingRule<PositionGraph>;
|
||||||
impl GraphBasedRankingRule<PositionGraph> {
|
impl GraphBasedRankingRule<PositionGraph> {
|
||||||
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
||||||
Self::new_with_id("position".to_owned(), terms_matching_strategy)
|
Self::new_with_id(RankingRuleId::WordPosition, terms_matching_strategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Typo = GraphBasedRankingRule<TypoGraph>;
|
pub type Typo = GraphBasedRankingRule<TypoGraph>;
|
||||||
impl GraphBasedRankingRule<TypoGraph> {
|
impl GraphBasedRankingRule<TypoGraph> {
|
||||||
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
pub fn new(terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
||||||
Self::new_with_id("typo".to_owned(), terms_matching_strategy)
|
Self::new_with_id(RankingRuleId::Typo, terms_matching_strategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Exactness = GraphBasedRankingRule<ExactnessGraph>;
|
pub type Exactness = GraphBasedRankingRule<ExactnessGraph>;
|
||||||
impl GraphBasedRankingRule<ExactnessGraph> {
|
impl GraphBasedRankingRule<ExactnessGraph> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::new_with_id("exactness".to_owned(), None)
|
Self::new_with_id(RankingRuleId::Exactness, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A generic graph-based ranking rule
|
/// A generic graph-based ranking rule
|
||||||
pub struct GraphBasedRankingRule<G: RankingRuleGraphTrait> {
|
pub struct GraphBasedRankingRule<G: RankingRuleGraphTrait> {
|
||||||
id: String,
|
id: RankingRuleId,
|
||||||
terms_matching_strategy: Option<TermsMatchingStrategy>,
|
terms_matching_strategy: Option<TermsMatchingStrategy>,
|
||||||
// When the ranking rule is not iterating over its buckets,
|
// When the ranking rule is not iterating over its buckets,
|
||||||
// its state is `None`.
|
// its state is `None`.
|
||||||
@@ -102,7 +105,10 @@ pub struct GraphBasedRankingRule<G: RankingRuleGraphTrait> {
|
|||||||
}
|
}
|
||||||
impl<G: RankingRuleGraphTrait> GraphBasedRankingRule<G> {
|
impl<G: RankingRuleGraphTrait> GraphBasedRankingRule<G> {
|
||||||
/// Creates the ranking rule with the given identifier
|
/// Creates the ranking rule with the given identifier
|
||||||
pub fn new_with_id(id: String, terms_matching_strategy: Option<TermsMatchingStrategy>) -> Self {
|
pub fn new_with_id(
|
||||||
|
id: RankingRuleId,
|
||||||
|
terms_matching_strategy: Option<TermsMatchingStrategy>,
|
||||||
|
) -> Self {
|
||||||
Self { id, terms_matching_strategy, state: None }
|
Self { id, terms_matching_strategy, state: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +130,7 @@ pub struct GraphBasedRankingRuleState<G: RankingRuleGraphTrait> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBasedRankingRule<G> {
|
impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBasedRankingRule<G> {
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> RankingRuleId {
|
||||||
self.id.clone()
|
self.id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +225,9 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
_time_budget: &TimeBudget,
|
_time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<QueryGraph>>> {
|
) -> Result<Option<RankingRuleOutput<QueryGraph>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
// Will crash if `next_bucket` is called before `start_iteration` or after `end_iteration`,
|
// Will crash if `next_bucket` is called before `start_iteration` or after `end_iteration`,
|
||||||
// should never happen
|
// should never happen
|
||||||
let mut state = self.state.take().unwrap();
|
let mut state = self.state.take().unwrap();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::search::new::ranking_rule_graph::{
|
|||||||
ProximityGraph, RankingRuleGraph, RankingRuleGraphTrait, TypoCondition, TypoGraph,
|
ProximityGraph, RankingRuleGraph, RankingRuleGraphTrait, TypoCondition, TypoGraph,
|
||||||
WordsCondition, WordsGraph,
|
WordsCondition, WordsGraph,
|
||||||
};
|
};
|
||||||
use crate::search::new::ranking_rules::BoxRankingRule;
|
use crate::search::new::ranking_rules::{BoxRankingRule, RankingRuleId};
|
||||||
use crate::search::new::{QueryGraph, QueryNode, RankingRule, SearchContext, SearchLogger};
|
use crate::search::new::{QueryGraph, QueryNode, RankingRule, SearchContext, SearchLogger};
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
@@ -45,13 +45,26 @@ enum Location {
|
|||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RankingRuleId> for Location {
|
||||||
|
fn from(ranking_rule_id: RankingRuleId) -> Self {
|
||||||
|
match ranking_rule_id {
|
||||||
|
RankingRuleId::Words => Self::Words,
|
||||||
|
RankingRuleId::Typo => Self::Typo,
|
||||||
|
RankingRuleId::Proximity => Self::Proximity,
|
||||||
|
RankingRuleId::AttributePosition => Self::Fid,
|
||||||
|
RankingRuleId::WordPosition => Self::Position,
|
||||||
|
_ => Self::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct VisualSearchLogger {
|
pub struct VisualSearchLogger {
|
||||||
initial_query: Option<QueryGraph>,
|
initial_query: Option<QueryGraph>,
|
||||||
initial_query_time: Option<Instant>,
|
initial_query_time: Option<Instant>,
|
||||||
query_for_universe: Option<QueryGraph>,
|
query_for_universe: Option<QueryGraph>,
|
||||||
initial_universe: Option<RoaringBitmap>,
|
initial_universe: Option<RoaringBitmap>,
|
||||||
ranking_rules_ids: Option<Vec<String>>,
|
ranking_rules_ids: Option<Vec<RankingRuleId>>,
|
||||||
events: Vec<SearchEvents>,
|
events: Vec<SearchEvents>,
|
||||||
location: Vec<Location>,
|
location: Vec<Location>,
|
||||||
}
|
}
|
||||||
@@ -84,14 +97,7 @@ impl SearchLogger<QueryGraph> for VisualSearchLogger {
|
|||||||
ranking_rule_idx,
|
ranking_rule_idx,
|
||||||
universe_len: universe.len(),
|
universe_len: universe.len(),
|
||||||
});
|
});
|
||||||
self.location.push(match ranking_rule.id().as_str() {
|
self.location.push(ranking_rule.id().into());
|
||||||
"words" => Location::Words,
|
|
||||||
"typo" => Location::Typo,
|
|
||||||
"proximity" => Location::Proximity,
|
|
||||||
"fid" => Location::Fid,
|
|
||||||
"position" => Location::Position,
|
|
||||||
_ => Location::Other,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_bucket_ranking_rule(
|
fn next_bucket_ranking_rule(
|
||||||
|
|||||||
@@ -498,12 +498,14 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::{execute_search, filtered_universe, SearchContext, TimeBudget};
|
use crate::{execute_search, filtered_universe, SearchContext, TimeBudget};
|
||||||
|
|
||||||
impl<'a> MatcherBuilder<'a> {
|
impl<'a> MatcherBuilder<'a> {
|
||||||
fn new_test(rtxn: &'a heed::RoTxn<'a>, index: &'a TempIndex, query: &str) -> Self {
|
fn new_test(rtxn: &'a heed::RoTxn<'a>, index: &'a TempIndex, query: &str) -> Self {
|
||||||
|
let progress = Progress::default();
|
||||||
let mut ctx = SearchContext::new(index, rtxn).unwrap();
|
let mut ctx = SearchContext::new(index, rtxn).unwrap();
|
||||||
let universe = filtered_universe(ctx.index, ctx.txn, &None).unwrap();
|
let universe = filtered_universe(ctx.index, ctx.txn, &None, &progress).unwrap();
|
||||||
let crate::search::PartialSearchResult { located_query_terms, .. } = execute_search(
|
let crate::search::PartialSearchResult { located_query_terms, .. } = execute_search(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
Some(query),
|
Some(query),
|
||||||
@@ -523,6 +525,7 @@ mod tests {
|
|||||||
TimeBudget::max(),
|
TimeBudget::max(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
&progress,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ use crate::constants::RESERVED_GEO_FIELD_NAME;
|
|||||||
use crate::documents::GeoSortParameter;
|
use crate::documents::GeoSortParameter;
|
||||||
use crate::index::PrefixSearch;
|
use crate::index::PrefixSearch;
|
||||||
use crate::localized_attributes_rules::LocalizedFieldIds;
|
use crate::localized_attributes_rules::LocalizedFieldIds;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
use crate::score_details::{ScoreDetails, ScoringStrategy};
|
||||||
use crate::search::new::distinct::apply_distinct_rule;
|
use crate::search::new::distinct::apply_distinct_rule;
|
||||||
|
use crate::search::steps::SearchStep;
|
||||||
use crate::vector::Embedder;
|
use crate::vector::Embedder;
|
||||||
use crate::{
|
use crate::{
|
||||||
AscDesc, DocumentId, FieldId, Filter, Index, Member, Result, TermsMatchingStrategy, TimeBudget,
|
AscDesc, DocumentId, FieldId, Filter, Index, Member, Result, TermsMatchingStrategy, TimeBudget,
|
||||||
@@ -294,7 +296,9 @@ fn resolve_universe(
|
|||||||
query_graph: &QueryGraph,
|
query_graph: &QueryGraph,
|
||||||
matching_strategy: TermsMatchingStrategy,
|
matching_strategy: TermsMatchingStrategy,
|
||||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<RoaringBitmap> {
|
) -> Result<RoaringBitmap> {
|
||||||
|
let _step = progress.update_progress_scoped(SearchStep::ResolvingUniverse);
|
||||||
resolve_maximally_reduced_query_graph(
|
resolve_maximally_reduced_query_graph(
|
||||||
ctx,
|
ctx,
|
||||||
initial_universe,
|
initial_universe,
|
||||||
@@ -632,8 +636,10 @@ pub fn filtered_universe(
|
|||||||
index: &Index,
|
index: &Index,
|
||||||
txn: &RoTxn<'_>,
|
txn: &RoTxn<'_>,
|
||||||
filters: &Option<Filter<'_>>,
|
filters: &Option<Filter<'_>>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<RoaringBitmap> {
|
) -> Result<RoaringBitmap> {
|
||||||
Ok(if let Some(filters) = filters {
|
Ok(if let Some(filters) = filters {
|
||||||
|
let _step = progress.update_progress_scoped(SearchStep::ComputingFilter);
|
||||||
filters.evaluate(txn, index)?
|
filters.evaluate(txn, index)?
|
||||||
} else {
|
} else {
|
||||||
index.documents_ids(txn)?
|
index.documents_ids(txn)?
|
||||||
@@ -658,6 +664,7 @@ pub fn execute_vector_search(
|
|||||||
quantized: bool,
|
quantized: bool,
|
||||||
time_budget: TimeBudget,
|
time_budget: TimeBudget,
|
||||||
ranking_score_threshold: Option<f64>,
|
ranking_score_threshold: Option<f64>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<PartialSearchResult> {
|
) -> Result<PartialSearchResult> {
|
||||||
check_sort_criteria(ctx, sort_criteria.as_ref())?;
|
check_sort_criteria(ctx, sort_criteria.as_ref())?;
|
||||||
|
|
||||||
@@ -692,6 +699,7 @@ pub fn execute_vector_search(
|
|||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
exhaustive_number_hits,
|
exhaustive_number_hits,
|
||||||
max_total_hits,
|
max_total_hits,
|
||||||
|
progress,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(PartialSearchResult {
|
Ok(PartialSearchResult {
|
||||||
@@ -725,12 +733,14 @@ pub fn execute_search(
|
|||||||
time_budget: TimeBudget,
|
time_budget: TimeBudget,
|
||||||
ranking_score_threshold: Option<f64>,
|
ranking_score_threshold: Option<f64>,
|
||||||
locales: Option<&Vec<Language>>,
|
locales: Option<&Vec<Language>>,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<PartialSearchResult> {
|
) -> Result<PartialSearchResult> {
|
||||||
check_sort_criteria(ctx, sort_criteria.as_ref())?;
|
check_sort_criteria(ctx, sort_criteria.as_ref())?;
|
||||||
|
|
||||||
let mut used_negative_operator = false;
|
let mut used_negative_operator = false;
|
||||||
let mut located_query_terms = None;
|
let mut located_query_terms = None;
|
||||||
let query_terms = if let Some(query) = query {
|
let query_terms = if let Some(query) = query {
|
||||||
|
progress.update_progress(SearchStep::TokenizingQuery);
|
||||||
let span = tracing::trace_span!(target: "search::tokens", "tokenizer_builder");
|
let span = tracing::trace_span!(target: "search::tokens", "tokenizer_builder");
|
||||||
let entered = span.enter();
|
let entered = span.enter();
|
||||||
|
|
||||||
@@ -834,8 +844,14 @@ pub fn execute_search(
|
|||||||
terms_matching_strategy,
|
terms_matching_strategy,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
universe &=
|
universe &= resolve_universe(
|
||||||
resolve_universe(ctx, &universe, &graph, terms_matching_strategy, query_graph_logger)?;
|
ctx,
|
||||||
|
&universe,
|
||||||
|
&graph,
|
||||||
|
terms_matching_strategy,
|
||||||
|
query_graph_logger,
|
||||||
|
progress,
|
||||||
|
)?;
|
||||||
|
|
||||||
bucket_sort(
|
bucket_sort(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -851,6 +867,7 @@ pub fn execute_search(
|
|||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
exhaustive_number_hits,
|
exhaustive_number_hits,
|
||||||
max_total_hits,
|
max_total_hits,
|
||||||
|
progress,
|
||||||
)?
|
)?
|
||||||
} else {
|
} else {
|
||||||
let ranking_rules =
|
let ranking_rules =
|
||||||
@@ -869,6 +886,7 @@ pub fn execute_search(
|
|||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
exhaustive_number_hits,
|
exhaustive_number_hits,
|
||||||
max_total_hits,
|
max_total_hits,
|
||||||
|
progress,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -59,19 +59,19 @@ impl RankingRuleGraphTrait for FidGraph {
|
|||||||
let mut all_fields = FxHashSet::default();
|
let mut all_fields = FxHashSet::default();
|
||||||
let mut current_max_weight = 0;
|
let mut current_max_weight = 0;
|
||||||
for word in term.term_subset.all_single_words_except_prefix_db(ctx)? {
|
for word in term.term_subset.all_single_words_except_prefix_db(ctx)? {
|
||||||
let fields = ctx.get_db_word_fids(word.interned())?;
|
let fields = dbg!(ctx.get_db_word_fids(word.interned())?);
|
||||||
all_fields.extend(fields);
|
all_fields.extend(fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
for phrase in term.term_subset.all_phrases(ctx)? {
|
for phrase in term.term_subset.all_phrases(ctx)? {
|
||||||
for &word in phrase.words(ctx).iter().flatten() {
|
for &word in phrase.words(ctx).iter().flatten() {
|
||||||
let fields = ctx.get_db_word_fids(word)?;
|
let fields = dbg!(ctx.get_db_word_fids(word)?);
|
||||||
all_fields.extend(fields);
|
all_fields.extend(fields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(word_prefix) = term.term_subset.use_prefix_db(ctx) {
|
if let Some(word_prefix) = term.term_subset.use_prefix_db(ctx) {
|
||||||
let fields = ctx.get_db_word_prefix_fids(word_prefix.interned())?;
|
let fields = dbg!(ctx.get_db_word_prefix_fids(word_prefix.interned())?);
|
||||||
all_fields.extend(fields);
|
all_fields.extend(fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ use roaring::RoaringBitmap;
|
|||||||
|
|
||||||
use super::logger::SearchLogger;
|
use super::logger::SearchLogger;
|
||||||
use super::{QueryGraph, SearchContext};
|
use super::{QueryGraph, SearchContext};
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::ScoreDetails;
|
use crate::score_details::ScoreDetails;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::{Result, TimeBudget};
|
use crate::{Result, TimeBudget};
|
||||||
|
|
||||||
/// An internal trait implemented by only [`PlaceholderQuery`] and [`QueryGraph`]
|
/// An internal trait implemented by only [`PlaceholderQuery`] and [`QueryGraph`]
|
||||||
@@ -24,7 +26,7 @@ pub type BoxRankingRule<'ctx, Query> = Box<dyn RankingRule<'ctx, Query> + 'ctx>;
|
|||||||
/// (i.e. the read transaction and the cache) and over `Query`, which
|
/// (i.e. the read transaction and the cache) and over `Query`, which
|
||||||
/// can be either [`PlaceholderQuery`] or [`QueryGraph`].
|
/// can be either [`PlaceholderQuery`] or [`QueryGraph`].
|
||||||
pub trait RankingRule<'ctx, Query: RankingRuleQueryTrait> {
|
pub trait RankingRule<'ctx, Query: RankingRuleQueryTrait> {
|
||||||
fn id(&self) -> String;
|
fn id(&self) -> RankingRuleId;
|
||||||
|
|
||||||
/// Prepare the ranking rule such that it can start iterating over its
|
/// Prepare the ranking rule such that it can start iterating over its
|
||||||
/// buckets using [`next_bucket`](RankingRule::next_bucket).
|
/// buckets using [`next_bucket`](RankingRule::next_bucket).
|
||||||
@@ -56,6 +58,7 @@ pub trait RankingRule<'ctx, Query: RankingRuleQueryTrait> {
|
|||||||
logger: &mut dyn SearchLogger<Query>,
|
logger: &mut dyn SearchLogger<Query>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
time_budget: &TimeBudget,
|
time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<Query>>>;
|
) -> Result<Option<RankingRuleOutput<Query>>>;
|
||||||
|
|
||||||
/// Return the next bucket of this ranking rule, if doing so can be done without blocking
|
/// Return the next bucket of this ranking rule, if doing so can be done without blocking
|
||||||
@@ -69,7 +72,9 @@ pub trait RankingRule<'ctx, Query: RankingRuleQueryTrait> {
|
|||||||
_ctx: &mut SearchContext<'ctx>,
|
_ctx: &mut SearchContext<'ctx>,
|
||||||
_logger: &mut dyn SearchLogger<Query>,
|
_logger: &mut dyn SearchLogger<Query>,
|
||||||
_universe: &RoaringBitmap,
|
_universe: &RoaringBitmap,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Poll<RankingRuleOutput<Query>>> {
|
) -> Result<Poll<RankingRuleOutput<Query>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
Ok(Poll::Pending)
|
Ok(Poll::Pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,3 +98,54 @@ pub struct RankingRuleOutput<Q> {
|
|||||||
/// The score for the candidates of the current bucket
|
/// The score for the candidates of the current bucket
|
||||||
pub score: ScoreDetails,
|
pub score: ScoreDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum RankingRuleId {
|
||||||
|
Words,
|
||||||
|
Typo,
|
||||||
|
Proximity,
|
||||||
|
AttributePosition,
|
||||||
|
WordPosition,
|
||||||
|
Exactness,
|
||||||
|
Sort,
|
||||||
|
GeoSort,
|
||||||
|
VectorSort,
|
||||||
|
Asc(String),
|
||||||
|
Desc(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for RankingRuleId {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
RankingRuleId::Words => write!(f, "words"),
|
||||||
|
RankingRuleId::Typo => write!(f, "typo"),
|
||||||
|
RankingRuleId::Proximity => write!(f, "proximity"),
|
||||||
|
RankingRuleId::AttributePosition => write!(f, "attribute_position"),
|
||||||
|
RankingRuleId::WordPosition => write!(f, "word_position"),
|
||||||
|
RankingRuleId::Exactness => write!(f, "exactness"),
|
||||||
|
RankingRuleId::Sort => write!(f, "sort"),
|
||||||
|
RankingRuleId::GeoSort => write!(f, "geo_sort"),
|
||||||
|
RankingRuleId::VectorSort => write!(f, "vector_sort"),
|
||||||
|
RankingRuleId::Asc(field_name) => write!(f, "asc:{}", field_name),
|
||||||
|
RankingRuleId::Desc(field_name) => write!(f, "desc:{}", field_name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RankingRuleId> for ComputingBucketSortStep {
|
||||||
|
fn from(ranking_rule_id: RankingRuleId) -> Self {
|
||||||
|
match ranking_rule_id {
|
||||||
|
RankingRuleId::Words => Self::Words,
|
||||||
|
RankingRuleId::Typo => Self::Typo,
|
||||||
|
RankingRuleId::Proximity => Self::Proximity,
|
||||||
|
RankingRuleId::AttributePosition => Self::AttributePosition,
|
||||||
|
RankingRuleId::WordPosition => Self::WordPosition,
|
||||||
|
RankingRuleId::Exactness => Self::Exactness,
|
||||||
|
RankingRuleId::Sort => Self::Sort,
|
||||||
|
RankingRuleId::GeoSort => Self::GeoSort,
|
||||||
|
RankingRuleId::VectorSort => Self::VectorSort,
|
||||||
|
RankingRuleId::Asc(_) => Self::Asc,
|
||||||
|
RankingRuleId::Desc(_) => Self::Desc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ use super::logger::SearchLogger;
|
|||||||
use super::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait, SearchContext};
|
use super::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait, SearchContext};
|
||||||
use crate::heed_codec::facet::{FacetGroupKeyCodec, OrderedF64Codec};
|
use crate::heed_codec::facet::{FacetGroupKeyCodec, OrderedF64Codec};
|
||||||
use crate::heed_codec::{BytesRefCodec, StrRefCodec};
|
use crate::heed_codec::{BytesRefCodec, StrRefCodec};
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{self, ScoreDetails};
|
use crate::score_details::{self, ScoreDetails};
|
||||||
use crate::search::facet::{ascending_facet_sort, descending_facet_sort};
|
use crate::search::facet::{ascending_facet_sort, descending_facet_sort};
|
||||||
|
use crate::search::new::ranking_rules::RankingRuleId;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::{FieldId, Index, Result, TimeBudget};
|
use crate::{FieldId, Index, Result, TimeBudget};
|
||||||
|
|
||||||
pub trait RankingRuleOutputIter<'ctx, Query> {
|
pub trait RankingRuleOutputIter<'ctx, Query> {
|
||||||
@@ -84,9 +87,13 @@ impl<'ctx, Query> Sort<'ctx, Query> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, Query: RankingRuleQueryTrait> RankingRule<'ctx, Query> for Sort<'ctx, Query> {
|
impl<'ctx, Query: RankingRuleQueryTrait> RankingRule<'ctx, Query> for Sort<'ctx, Query> {
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> RankingRuleId {
|
||||||
let Self { field_name, is_ascending, .. } = self;
|
let Self { field_name, is_ascending, .. } = self;
|
||||||
format!("{field_name}:{}", if *is_ascending { "asc" } else { "desc" })
|
if *is_ascending {
|
||||||
|
RankingRuleId::Asc(field_name.clone())
|
||||||
|
} else {
|
||||||
|
RankingRuleId::Desc(field_name.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, target = "search::sort")]
|
#[tracing::instrument(level = "trace", skip_all, target = "search::sort")]
|
||||||
@@ -196,7 +203,9 @@ impl<'ctx, Query: RankingRuleQueryTrait> RankingRule<'ctx, Query> for Sort<'ctx,
|
|||||||
_logger: &mut dyn SearchLogger<Query>,
|
_logger: &mut dyn SearchLogger<Query>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
_time_budget: &TimeBudget,
|
_time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<Query>>> {
|
) -> Result<Option<RankingRuleOutput<Query>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
let iter = self.iter.as_mut().unwrap();
|
let iter = self.iter.as_mut().unwrap();
|
||||||
if let Some(mut bucket) = iter.next_bucket()? {
|
if let Some(mut bucket) = iter.next_bucket()? {
|
||||||
bucket.candidates &= universe;
|
bucket.candidates &= universe;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::{db_snap, Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{db_snap, Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -119,7 +119,7 @@ fn test_attribute_fid_simple() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -147,7 +147,7 @@ fn test_attribute_fid_ngrams() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::{db_snap, Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{db_snap, Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -134,7 +134,7 @@ fn test_attribute_position_simple() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("quick brown");
|
s.query("quick brown");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -150,7 +150,7 @@ fn test_attribute_position_repeated() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("a a a a a");
|
s.query("a a a a a");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -167,7 +167,7 @@ fn test_attribute_position_different_fields() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("quick brown");
|
s.query("quick brown");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -184,7 +184,7 @@ fn test_attribute_position_ngrams() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("quick brown");
|
s.query("quick brown");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::score_details::{ScoreDetails, ScoringStrategy};
|
|||||||
use crate::update::Setting;
|
use crate::update::Setting;
|
||||||
use crate::vector::settings::EmbeddingSettings;
|
use crate::vector::settings::EmbeddingSettings;
|
||||||
use crate::vector::{Embedder, EmbedderOptions};
|
use crate::vector::{Embedder, EmbedderOptions};
|
||||||
use crate::{Criterion, Filter, FilterableAttributesRule, Search, TimeBudget};
|
use crate::{Criterion, Filter, FilterableAttributesRule, TimeBudget};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -61,7 +61,7 @@ fn basic_degraded_search() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
search.query("hello puppy kefir");
|
search.query("hello puppy kefir");
|
||||||
search.limit(3);
|
search.limit(3);
|
||||||
search.time_budget(TimeBudget::new(Duration::from_millis(0)));
|
search.time_budget(TimeBudget::new(Duration::from_millis(0)));
|
||||||
@@ -75,7 +75,7 @@ fn degraded_search_cannot_skip_filter() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
search.query("hello puppy kefir");
|
search.query("hello puppy kefir");
|
||||||
search.limit(100);
|
search.limit(100);
|
||||||
search.time_budget(TimeBudget::new(Duration::from_millis(0)));
|
search.time_budget(TimeBudget::new(Duration::from_millis(0)));
|
||||||
@@ -96,7 +96,7 @@ fn degraded_search_and_score_details() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
search.query("hello puppy kefir");
|
search.query("hello puppy kefir");
|
||||||
search.limit(4);
|
search.limit(4);
|
||||||
search.scoring_strategy(ScoringStrategy::Detailed);
|
search.scoring_strategy(ScoringStrategy::Detailed);
|
||||||
@@ -560,7 +560,7 @@ fn degraded_search_and_score_details_vector() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
|
|
||||||
let embedder = Arc::new(
|
let embedder = Arc::new(
|
||||||
Embedder::new(
|
Embedder::new(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use maplit::hashset;
|
|||||||
use super::collect_field_values;
|
use super::collect_field_values;
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::{
|
use crate::{
|
||||||
AscDesc, Criterion, FilterableAttributesRule, Index, Member, Search, SearchResult,
|
AscDesc, Criterion, FilterableAttributesRule, Index, Member, SearchResult,
|
||||||
TermsMatchingStrategy,
|
TermsMatchingStrategy,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ fn test_distinct_placeholder_no_ranking_rules() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.distinct(S("letter"));
|
s.distinct(S("letter"));
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0, 2, 5, 8, 9, 15, 18, 20, 21, 24, 25, 26]");
|
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0, 2, 5, 8, 9, 15, 18, 20, 21, 24, 25, 26]");
|
||||||
@@ -275,7 +275,7 @@ fn test_distinct_at_search_placeholder_no_ranking_rules() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let s = Search::new(&txn, &index);
|
let s = index.search(&txn);
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0, 2, 5, 8, 9, 15, 18, 20, 21, 24, 25, 26]");
|
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0, 2, 5, 8, 9, 15, 18, 20, 21, 24, 25, 26]");
|
||||||
let distinct_values = verify_distinct(&index, &txn, None, &documents_ids);
|
let distinct_values = verify_distinct(&index, &txn, None, &documents_ids);
|
||||||
@@ -308,7 +308,7 @@ fn test_distinct_placeholder_sort() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank1")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank1")))]);
|
||||||
|
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -348,7 +348,7 @@ fn test_distinct_placeholder_sort() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
||||||
|
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -388,7 +388,7 @@ fn test_distinct_placeholder_sort() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.sort_criteria(vec![
|
s.sort_criteria(vec![
|
||||||
AscDesc::Desc(Member::Field(S("letter"))),
|
AscDesc::Desc(Member::Field(S("letter"))),
|
||||||
AscDesc::Desc(Member::Field(S("rank1"))),
|
AscDesc::Desc(Member::Field(S("rank1"))),
|
||||||
@@ -443,7 +443,7 @@ fn test_distinct_words() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
|
|
||||||
@@ -496,7 +496,7 @@ fn test_distinct_sort_words() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
||||||
@@ -569,7 +569,7 @@ fn test_distinct_all_candidates() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank1")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank1")))]);
|
||||||
s.exhaustive_number_hits(true);
|
s.exhaustive_number_hits(true);
|
||||||
@@ -592,7 +592,7 @@ fn test_distinct_typo() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ This module tests the following properties about the exactness ranking rule:
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index_simple_ordered() -> TempIndex {
|
fn create_index_simple_ordered() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -471,7 +471,7 @@ fn test_exactness_simple_ordered() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -503,7 +503,7 @@ fn test_exactness_simple_reversed() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -526,7 +526,7 @@ fn test_exactness_simple_reversed() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -556,7 +556,7 @@ fn test_exactness_simple_random() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -585,7 +585,7 @@ fn test_exactness_attribute_starts_with_simple() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("this balcony");
|
s.query("this balcony");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -611,7 +611,7 @@ fn test_exactness_attribute_starts_with_phrase() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("\"overlooking the sea\" is a beautiful balcony");
|
s.query("\"overlooking the sea\" is a beautiful balcony");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -631,7 +631,7 @@ fn test_exactness_attribute_starts_with_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("overlooking the sea is a beautiful balcony");
|
s.query("overlooking the sea is a beautiful balcony");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -660,7 +660,7 @@ fn test_exactness_all_candidates_with_typo() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("overlocking the sea is a beautiful balcony");
|
s.query("overlocking the sea is a beautiful balcony");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -696,7 +696,7 @@ fn test_exactness_after_words() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -744,7 +744,7 @@ fn test_words_after_exactness() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -792,7 +792,7 @@ fn test_proximity_after_exactness() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -829,7 +829,7 @@ fn test_proximity_after_exactness() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -862,7 +862,7 @@ fn test_exactness_followed_by_typo_prefer_no_typo_prefix() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("quick brown fox extra");
|
s.query("quick brown fox extra");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -897,7 +897,7 @@ fn test_typo_followed_by_exactness() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.query("extraordinarily quick brown fox");
|
s.query("extraordinarily quick brown fox");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ fn test_geo_sort() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|
||||||
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
||||||
@@ -118,7 +118,7 @@ fn test_geo_sort_with_following_ranking_rules() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![
|
s.sort_criteria(vec![
|
||||||
AscDesc::Asc(Member::Geo([0., 0.])),
|
AscDesc::Asc(Member::Geo([0., 0.])),
|
||||||
@@ -159,7 +159,7 @@ fn test_geo_sort_reached_max_bucket_size() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.geo_max_bucket_size(2);
|
s.geo_max_bucket_size(2);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![
|
s.sort_criteria(vec![
|
||||||
@@ -219,7 +219,7 @@ fn test_geo_sort_around_the_edge_of_the_flat_earth() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|
||||||
// --- asc
|
// --- asc
|
||||||
@@ -295,7 +295,7 @@ fn geo_sort_mixed_with_words() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ fn geo_sort_without_any_geo_faceted_documents() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&rtxn, &index);
|
let mut s = index.search(&rtxn);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
s.sort_criteria(vec![AscDesc::Asc(Member::Geo([0., 0.]))]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::{Search, SearchResult};
|
use crate::SearchResult;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_kanji_language_detection() {
|
fn test_kanji_language_detection() {
|
||||||
@@ -14,7 +14,7 @@ fn test_kanji_language_detection() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let txn = index.write_txn().unwrap();
|
let txn = index.write_txn().unwrap();
|
||||||
let mut search = Search::new(&txn, &index);
|
let mut search = index.search(&txn);
|
||||||
|
|
||||||
search.query("東京");
|
search.query("東京");
|
||||||
let SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ This module tests the following properties:
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -78,7 +78,7 @@ fn test_2gram_simple() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("sun flower");
|
s.query("sun flower");
|
||||||
@@ -109,7 +109,7 @@ fn test_3gram_simple() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sun flower s are");
|
s.query("sun flower s are");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -129,7 +129,7 @@ fn test_2gram_typo() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sun flawer");
|
s.query("sun flawer");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -159,7 +159,7 @@ fn test_no_disable_ngrams() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sun flower ");
|
s.query("sun flower ");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -185,7 +185,7 @@ fn test_2gram_prefix() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sun flow");
|
s.query("sun flow");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -214,7 +214,7 @@ fn test_3gram_prefix() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("su nf l");
|
s.query("su nf l");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -237,7 +237,7 @@ fn test_split_words() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sunflower ");
|
s.query("sunflower ");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -266,7 +266,7 @@ fn test_disable_split_words() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sunflower ");
|
s.query("sunflower ");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -286,7 +286,7 @@ fn test_2gram_split_words() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sunf lower");
|
s.query("sunf lower");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -310,7 +310,7 @@ fn test_3gram_no_split_words() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sunf lo wer");
|
s.query("sunf lo wer");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -333,7 +333,7 @@ fn test_3gram_no_typos() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("sunf la wer");
|
s.query("sunf la wer");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -352,7 +352,7 @@ fn test_no_ngram_phrases() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("\"sun\" flower");
|
s.query("\"sun\" flower");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -366,7 +366,7 @@ fn test_no_ngram_phrases() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("\"sun\" \"flower\"");
|
s.query("\"sun\" \"flower\"");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -385,7 +385,7 @@ fn test_short_split_words() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("xyz");
|
s.query("xyz");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -412,7 +412,7 @@ fn test_split_words_never_disabled() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the sunflower is tall");
|
s.query("the sunflower is tall");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_simple_index() -> TempIndex {
|
fn create_simple_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -268,7 +268,7 @@ fn test_proximity_simple() {
|
|||||||
let index = create_simple_index();
|
let index = create_simple_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
@@ -295,7 +295,7 @@ fn test_proximity_split_word() {
|
|||||||
let index = create_edge_cases_index();
|
let index = create_edge_cases_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("sunflower wilting");
|
s.query("sunflower wilting");
|
||||||
@@ -315,7 +315,7 @@ fn test_proximity_split_word() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("\"sun flower\" wilting");
|
s.query("\"sun flower\" wilting");
|
||||||
@@ -342,7 +342,7 @@ fn test_proximity_split_word() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("xyz wilting");
|
s.query("xyz wilting");
|
||||||
@@ -365,7 +365,7 @@ fn test_proximity_prefix_db() {
|
|||||||
let index = create_edge_cases_index();
|
let index = create_edge_cases_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("best s");
|
s.query("best s");
|
||||||
@@ -390,7 +390,7 @@ fn test_proximity_prefix_db() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Difference when using the `su` prefix, which is not in the prefix DB
|
// Difference when using the `su` prefix, which is not in the prefix DB
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("best su");
|
s.query("best su");
|
||||||
@@ -417,7 +417,7 @@ fn test_proximity_prefix_db() {
|
|||||||
// **proximity** prefix DB. In that case, its sprximity score will always be
|
// **proximity** prefix DB. In that case, its sprximity score will always be
|
||||||
// the maximum. This happens for prefixes that are larger than 2 bytes.
|
// the maximum. This happens for prefixes that are larger than 2 bytes.
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("best win");
|
s.query("best win");
|
||||||
@@ -441,7 +441,7 @@ fn test_proximity_prefix_db() {
|
|||||||
|
|
||||||
// Now using `wint`, which is not in the prefix DB:
|
// Now using `wint`, which is not in the prefix DB:
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("best wint");
|
s.query("best wint");
|
||||||
@@ -465,7 +465,7 @@ fn test_proximity_prefix_db() {
|
|||||||
|
|
||||||
// and using `wi` which is in the prefix DB and proximity prefix DB
|
// and using `wi` which is in the prefix DB and proximity prefix DB
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("best wi");
|
s.query("best wi");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ implemented.
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -57,7 +57,7 @@ fn test_trap_basic() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("summer holiday");
|
s.query("summer holiday");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ use meili_snap::insta;
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{
|
use crate::{score_details, AscDesc, Criterion, Member, SearchResult, TermsMatchingStrategy};
|
||||||
score_details, AscDesc, Criterion, Member, Search, SearchResult, TermsMatchingStrategy,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -184,7 +182,7 @@ fn test_sort() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("letter")))]);
|
||||||
@@ -219,7 +217,7 @@ fn test_sort() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("rank")))]);
|
||||||
@@ -254,7 +252,7 @@ fn test_sort() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Asc(Member::Field(S("vague")))]);
|
s.sort_criteria(vec![AscDesc::Asc(Member::Field(S("vague")))]);
|
||||||
@@ -289,7 +287,7 @@ fn test_sort() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("vague")))]);
|
s.sort_criteria(vec![AscDesc::Desc(Member::Field(S("vague")))]);
|
||||||
@@ -338,7 +336,7 @@ fn test_redacted() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.sort_criteria(vec![
|
s.sort_criteria(vec![
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use std::collections::BTreeSet;
|
|||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::{Search, SearchResult, TermsMatchingStrategy};
|
use crate::{SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -79,7 +79,7 @@ fn test_ignore_stop_words() {
|
|||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
// `the` is treated as a prefix here, so it's not ignored
|
// `the` is treated as a prefix here, so it's not ignored
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("xyz to the");
|
s.query("xyz to the");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -132,7 +132,7 @@ fn test_ignore_stop_words() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// `xyz` is treated as a prefix here, so it's not ignored
|
// `xyz` is treated as a prefix here, so it's not ignored
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("to the xyz");
|
s.query("to the xyz");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -185,7 +185,7 @@ fn test_ignore_stop_words() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// `xyz` is not treated as a prefix anymore because of the trailing space, so it's ignored
|
// `xyz` is not treated as a prefix anymore because of the trailing space, so it's ignored
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("to the xyz ");
|
s.query("to the xyz ");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -237,7 +237,7 @@ fn test_ignore_stop_words() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("to the dragon xyz");
|
s.query("to the dragon xyz");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -296,7 +296,7 @@ fn test_stop_words_in_phrase() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"how to train your dragon\"");
|
s.query("\"how to train your dragon\"");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -389,7 +389,7 @@ fn test_stop_words_in_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("how \"to\" train \"the");
|
s.query("how \"to\" train \"the");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -441,7 +441,7 @@ fn test_stop_words_in_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("how \"to\" train \"The dragon");
|
s.query("how \"to\" train \"The dragon");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -449,7 +449,7 @@ fn test_stop_words_in_phrase() {
|
|||||||
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[3, 6, 5]");
|
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[3, 6, 5]");
|
||||||
insta::assert_snapshot!(format!("{document_scores:#?}"));
|
insta::assert_snapshot!(format!("{document_scores:#?}"));
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"to\"");
|
s.query("\"to\"");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -157,7 +157,7 @@ fn test_no_typo() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -182,7 +182,7 @@ fn test_default_typo() {
|
|||||||
insta::assert_debug_snapshot!(tt, @"9");
|
insta::assert_debug_snapshot!(tt, @"9");
|
||||||
|
|
||||||
// 0 typo
|
// 0 typo
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -202,7 +202,7 @@ fn test_default_typo() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// 1 typo on one word, replaced letter
|
// 1 typo on one word, replaced letter
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quack brown fox jumps over the lazy dog");
|
s.query("the quack brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -216,7 +216,7 @@ fn test_default_typo() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// 1 typo on one word, missing letter, extra letter
|
// 1 typo on one word, missing letter, extra letter
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quicest brownest fox jummps over the laziest dog");
|
s.query("the quicest brownest fox jummps over the laziest dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -235,7 +235,7 @@ fn test_phrase_no_typo_allowed() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the \"quick brewn\" fox jumps over the lazy dog");
|
s.query("the \"quick brewn\" fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -265,7 +265,7 @@ fn test_typo_exact_word() {
|
|||||||
insta::assert_debug_snapshot!(tt, @"9");
|
insta::assert_debug_snapshot!(tt, @"9");
|
||||||
|
|
||||||
// don't match quivk
|
// don't match quivk
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -279,7 +279,7 @@ fn test_typo_exact_word() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Don't match quick
|
// Don't match quick
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quack brown fox jumps over the lazy dog");
|
s.query("the quack brown fox jumps over the lazy dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -287,7 +287,7 @@ fn test_typo_exact_word() {
|
|||||||
insta::assert_snapshot!(format!("{document_scores:?}"), @"[]");
|
insta::assert_snapshot!(format!("{document_scores:?}"), @"[]");
|
||||||
|
|
||||||
// words not in exact_words (quicest, jummps) have normal typo handling
|
// words not in exact_words (quicest, jummps) have normal typo handling
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("the quicest brownest fox jummps over the laziest dog");
|
s.query("the quicest brownest fox jummps over the laziest dog");
|
||||||
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
let SearchResult { documents_ids, document_scores, .. } = s.execute().unwrap();
|
||||||
@@ -301,7 +301,7 @@ fn test_typo_exact_word() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// exact words do not disable prefix (sunflowering OK, but no sunflowar)
|
// exact words do not disable prefix (sunflowering OK, but no sunflowar)
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("network interconnection sunflower");
|
s.query("network interconnection sunflower");
|
||||||
@@ -340,7 +340,7 @@ fn test_typo_exact_attribute() {
|
|||||||
insta::assert_debug_snapshot!(tt, @"9");
|
insta::assert_debug_snapshot!(tt, @"9");
|
||||||
|
|
||||||
// Exact match returns both exact attributes and tolerant ones.
|
// Exact match returns both exact attributes and tolerant ones.
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
@@ -365,7 +365,7 @@ fn test_typo_exact_attribute() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// 1 typo only returns the tolerant attribute
|
// 1 typo only returns the tolerant attribute
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quidk brown fox jumps over the lazy dog");
|
s.query("the quidk brown fox jumps over the lazy dog");
|
||||||
@@ -386,7 +386,7 @@ fn test_typo_exact_attribute() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// combine with exact words
|
// combine with exact words
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quivk brown fox jumps over the lazy dog");
|
s.query("the quivk brown fox jumps over the lazy dog");
|
||||||
@@ -414,7 +414,7 @@ fn test_typo_exact_attribute() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
// No result in tolerant attribute
|
// No result in tolerant attribute
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quicest brownest fox jummps over the laziest dog");
|
s.query("the quicest brownest fox jummps over the laziest dog");
|
||||||
@@ -428,7 +428,7 @@ fn test_ngram_typos() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the extra lagant fox skyrocketed over the languorous dog");
|
s.query("the extra lagant fox skyrocketed over the languorous dog");
|
||||||
@@ -442,7 +442,7 @@ fn test_ngram_typos() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the ex tra lagant fox skyrocketed over the languorous dog");
|
s.query("the ex tra lagant fox skyrocketed over the languorous dog");
|
||||||
@@ -463,7 +463,7 @@ fn test_typo_ranking_rule_not_preceded_by_words_ranking_rule() {
|
|||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
@@ -499,7 +499,7 @@ fn test_typo_ranking_rule_not_preceded_by_words_ranking_rule() {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
@@ -517,7 +517,7 @@ fn test_typo_bucketing() {
|
|||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
// First do the search with just the Words ranking rule
|
// First do the search with just the Words ranking rule
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("network interconnection sunflower");
|
s.query("network interconnection sunflower");
|
||||||
@@ -545,7 +545,7 @@ fn test_typo_bucketing() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("network interconnection sunflower");
|
s.query("network interconnection sunflower");
|
||||||
@@ -564,7 +564,7 @@ fn test_typo_bucketing() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("network interconnection sun flower");
|
s.query("network interconnection sun flower");
|
||||||
@@ -600,7 +600,7 @@ fn test_typo_synonyms() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the quick brown fox jumps over the lackadaisical dog");
|
s.query("the quick brown fox jumps over the lackadaisical dog");
|
||||||
@@ -616,7 +616,7 @@ fn test_typo_synonyms() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
s.query("the fast brownish fox jumps over the lackadaisical dog");
|
s.query("the fast brownish fox jumps over the lackadaisical dog");
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ because the typo ranking rule before it only used the derivation `beautiful`.
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -87,7 +87,7 @@ fn test_trap_basic_and_complex1() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("beautiful summer");
|
s.query("beautiful summer");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -110,7 +110,7 @@ fn test_trap_complex2() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.query("delicious sweet dessert");
|
s.query("delicious sweet dessert");
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ This module tests the following properties:
|
|||||||
|
|
||||||
use crate::index::tests::TempIndex;
|
use crate::index::tests::TempIndex;
|
||||||
use crate::search::new::tests::collect_field_values;
|
use crate::search::new::tests::collect_field_values;
|
||||||
use crate::{Criterion, Search, SearchResult, TermsMatchingStrategy};
|
use crate::{Criterion, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
fn create_index() -> TempIndex {
|
fn create_index() -> TempIndex {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
@@ -131,7 +131,7 @@ fn test_words_tms_last_simple() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -166,7 +166,7 @@ fn test_words_tms_last_simple() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("extravagant the quick brown fox jumps over the lazy dog");
|
s.query("extravagant the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -180,7 +180,7 @@ fn test_words_tms_last_phrase() {
|
|||||||
let index = create_index();
|
let index = create_index();
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"the quick brown fox\" jumps over the lazy dog");
|
s.query("\"the quick brown fox\" jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -205,7 +205,7 @@ fn test_words_tms_last_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"the quick brown fox\" jumps over the \"lazy\" dog");
|
s.query("\"the quick brown fox\" jumps over the \"lazy\" dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -227,7 +227,7 @@ fn test_words_tms_last_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"the quick brown fox jumps over the lazy dog\"");
|
s.query("\"the quick brown fox jumps over the lazy dog\"");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -243,7 +243,7 @@ fn test_words_tms_last_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("\"the quick brown fox jumps over the lazy dog");
|
s.query("\"the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -270,7 +270,7 @@ fn test_words_proximity_tms_last_simple() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -305,7 +305,7 @@ fn test_words_proximity_tms_last_simple() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the brown quick fox jumps over the lazy dog");
|
s.query("the brown quick fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -351,7 +351,7 @@ fn test_words_proximity_tms_last_phrase() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the \"quick brown\" fox jumps over the lazy dog");
|
s.query("the \"quick brown\" fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -382,7 +382,7 @@ fn test_words_proximity_tms_last_phrase() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the \"quick brown\" \"fox jumps\" over the lazy dog");
|
s.query("the \"quick brown\" \"fox jumps\" over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
s.terms_matching_strategy(TermsMatchingStrategy::Last);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -421,7 +421,7 @@ fn test_words_tms_all() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("the quick brown fox jumps over the lazy dog");
|
s.query("the quick brown fox jumps over the lazy dog");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
@@ -447,7 +447,7 @@ fn test_words_tms_all() {
|
|||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = index.search(&txn);
|
||||||
s.query("extravagant");
|
s.query("extravagant");
|
||||||
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
s.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
s.scoring_strategy(crate::score_details::ScoringStrategy::Detailed);
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use roaring::RoaringBitmap;
|
|||||||
|
|
||||||
use super::ranking_rules::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait};
|
use super::ranking_rules::{RankingRule, RankingRuleOutput, RankingRuleQueryTrait};
|
||||||
use super::VectorStoreStats;
|
use super::VectorStoreStats;
|
||||||
|
use crate::progress::Progress;
|
||||||
use crate::score_details::{self, ScoreDetails};
|
use crate::score_details::{self, ScoreDetails};
|
||||||
|
use crate::search::new::ranking_rules::RankingRuleId;
|
||||||
|
use crate::search::steps::ComputingBucketSortStep;
|
||||||
use crate::vector::{DistributionShift, Embedder, VectorStore};
|
use crate::vector::{DistributionShift, Embedder, VectorStore};
|
||||||
use crate::{DocumentId, Result, SearchContext, SearchLogger, TimeBudget};
|
use crate::{DocumentId, Result, SearchContext, SearchLogger, TimeBudget};
|
||||||
|
|
||||||
@@ -94,8 +97,8 @@ impl<Q: RankingRuleQueryTrait> VectorSort<Q> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for VectorSort<Q> {
|
impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for VectorSort<Q> {
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> RankingRuleId {
|
||||||
"vector_sort".to_owned()
|
RankingRuleId::VectorSort
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, target = "search::vector_sort")]
|
#[tracing::instrument(level = "trace", skip_all, target = "search::vector_sort")]
|
||||||
@@ -123,7 +126,9 @@ impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for VectorSort<Q> {
|
|||||||
_logger: &mut dyn SearchLogger<Q>,
|
_logger: &mut dyn SearchLogger<Q>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
time_budget: &TimeBudget,
|
time_budget: &TimeBudget,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Option<RankingRuleOutput<Q>>> {
|
) -> Result<Option<RankingRuleOutput<Q>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
let query = self.query.as_ref().unwrap().clone();
|
let query = self.query.as_ref().unwrap().clone();
|
||||||
let vector_candidates = &self.vector_candidates & universe;
|
let vector_candidates = &self.vector_candidates & universe;
|
||||||
|
|
||||||
@@ -158,7 +163,7 @@ impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for VectorSort<Q> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.next_bucket(ctx, _logger, universe, time_budget)
|
self.next_bucket(ctx, _logger, universe, time_budget, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, target = "search::vector_sort")]
|
#[tracing::instrument(level = "trace", skip_all, target = "search::vector_sort")]
|
||||||
@@ -171,7 +176,9 @@ impl<'ctx, Q: RankingRuleQueryTrait> RankingRule<'ctx, Q> for VectorSort<Q> {
|
|||||||
_ctx: &mut SearchContext<'ctx>,
|
_ctx: &mut SearchContext<'ctx>,
|
||||||
_logger: &mut dyn SearchLogger<Q>,
|
_logger: &mut dyn SearchLogger<Q>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
|
progress: &Progress,
|
||||||
) -> Result<Poll<RankingRuleOutput<Q>>> {
|
) -> Result<Poll<RankingRuleOutput<Q>>> {
|
||||||
|
progress.update_progress(ComputingBucketSortStep::from(self.id()));
|
||||||
let query = self.query.as_ref().unwrap().clone();
|
let query = self.query.as_ref().unwrap().clone();
|
||||||
let vector_candidates = &self.vector_candidates & universe;
|
let vector_candidates = &self.vector_candidates & universe;
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,12 @@ impl<'a> Similar<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&self) -> Result<SearchResult> {
|
pub fn execute(&self) -> Result<SearchResult> {
|
||||||
let mut universe = filtered_universe(self.index, self.rtxn, &self.filter)?;
|
let mut universe = filtered_universe(
|
||||||
|
self.index,
|
||||||
|
self.rtxn,
|
||||||
|
&self.filter,
|
||||||
|
&crate::progress::Progress::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
// we never want to receive the docid
|
// we never want to receive the docid
|
||||||
universe.remove(self.id);
|
universe.remove(self.id);
|
||||||
|
|||||||
52
crates/milli/src/search/steps.rs
Normal file
52
crates/milli/src/search/steps.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use crate::make_enum_progress;
|
||||||
|
|
||||||
|
make_enum_progress! {
|
||||||
|
pub enum SearchStep {
|
||||||
|
PreparingSearch,
|
||||||
|
TokenizingQuery,
|
||||||
|
EmbeddingQuery,
|
||||||
|
ComputingFilter,
|
||||||
|
ResolvingUniverse,
|
||||||
|
ComputingBucketSort,
|
||||||
|
FormattingResults,
|
||||||
|
ComputingFacetDistribution,
|
||||||
|
FederatingResults,
|
||||||
|
ApplyingPersonalization,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_enum_progress! {
|
||||||
|
pub enum ComputingBucketSortStep {
|
||||||
|
Initializing,
|
||||||
|
MergingCandidates,
|
||||||
|
ApplyingDistinctRule,
|
||||||
|
Words,
|
||||||
|
Typo,
|
||||||
|
Proximity,
|
||||||
|
AttributePosition,
|
||||||
|
WordPosition,
|
||||||
|
Exactness,
|
||||||
|
Sort,
|
||||||
|
GeoSort,
|
||||||
|
VectorSort,
|
||||||
|
Asc,
|
||||||
|
Desc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_enum_progress! {
|
||||||
|
pub enum FederatingResultsStep {
|
||||||
|
WaitingForRemoteResults,
|
||||||
|
MergingFacets,
|
||||||
|
MergingResults,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_enum_progress! {
|
||||||
|
pub enum TotalProcessingTimeStep {
|
||||||
|
WaitingForPermit,
|
||||||
|
Searching,
|
||||||
|
FetchingSimilar,
|
||||||
|
PublishingAnalytics,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ pub(crate) struct TempIndex {
|
|||||||
pub inner: Index,
|
pub inner: Index,
|
||||||
pub indexer_config: IndexerConfig,
|
pub indexer_config: IndexerConfig,
|
||||||
pub index_documents_config: IndexDocumentsConfig,
|
pub index_documents_config: IndexDocumentsConfig,
|
||||||
|
pub progress: Progress,
|
||||||
_tempdir: TempDir,
|
_tempdir: TempDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,9 @@ impl TempIndex {
|
|||||||
let inner = Index::new(options, _tempdir.path(), true).unwrap();
|
let inner = Index::new(options, _tempdir.path(), true).unwrap();
|
||||||
let indexer_config = IndexerConfig::default();
|
let indexer_config = IndexerConfig::default();
|
||||||
let index_documents_config = IndexDocumentsConfig::default();
|
let index_documents_config = IndexDocumentsConfig::default();
|
||||||
Self { inner, indexer_config, index_documents_config, _tempdir }
|
let progress = Progress::default();
|
||||||
|
|
||||||
|
Self { inner, indexer_config, index_documents_config, progress, _tempdir }
|
||||||
}
|
}
|
||||||
/// Creates a temporary index, with a default `4096 * 2000` size. This should be enough for
|
/// Creates a temporary index, with a default `4096 * 2000` size. This should be enough for
|
||||||
/// most tests.
|
/// most tests.
|
||||||
@@ -210,6 +213,10 @@ impl TempIndex {
|
|||||||
pub fn delete_document(&self, external_document_id: &str) {
|
pub fn delete_document(&self, external_document_id: &str) {
|
||||||
self.delete_documents(vec![external_document_id.to_string()])
|
self.delete_documents(vec![external_document_id.to_string()])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn search<'a>(&'a self, rtxn: &'a heed::RoTxn<'a>) -> Search<'a> {
|
||||||
|
self.inner.search(rtxn, &self.progress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1095,7 +1102,7 @@ fn bug_3021_fourth() {
|
|||||||
"###);
|
"###);
|
||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
let search = Search::new(&rtxn, &index);
|
let search = index.search(&rtxn);
|
||||||
let SearchResult {
|
let SearchResult {
|
||||||
matching_words: _,
|
matching_words: _,
|
||||||
candidates: _,
|
candidates: _,
|
||||||
|
|||||||
@@ -1292,7 +1292,7 @@ mod tests {
|
|||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
// testing the simple query search
|
// testing the simple query search
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
search.query("document");
|
search.query("document");
|
||||||
search.terms_matching_strategy(TermsMatchingStrategy::default());
|
search.terms_matching_strategy(TermsMatchingStrategy::default());
|
||||||
// all documents should be returned
|
// all documents should be returned
|
||||||
@@ -1333,7 +1333,7 @@ mod tests {
|
|||||||
assert!(documents_ids.is_empty()); // nested is not searchable
|
assert!(documents_ids.is_empty()); // nested is not searchable
|
||||||
|
|
||||||
// testing the filters
|
// testing the filters
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = index.search(&rtxn);
|
||||||
search.filter(crate::Filter::from_str(r#"title = "The first document""#).unwrap().unwrap());
|
search.filter(crate::Filter::from_str(r#"title = "The first document""#).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]);
|
||||||
@@ -1358,6 +1358,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn index_documents_with_nested_primary_key() {
|
fn index_documents_with_nested_primary_key() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
|
let progress = Progress::default();
|
||||||
|
|
||||||
index
|
index
|
||||||
.update_settings(|settings| {
|
.update_settings(|settings| {
|
||||||
@@ -1397,7 +1398,7 @@ mod tests {
|
|||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
// testing the simple query search
|
// testing the simple query search
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = crate::Search::new(&rtxn, &index, &progress);
|
||||||
search.query("document");
|
search.query("document");
|
||||||
search.terms_matching_strategy(TermsMatchingStrategy::default());
|
search.terms_matching_strategy(TermsMatchingStrategy::default());
|
||||||
// all documents should be returned
|
// all documents should be returned
|
||||||
@@ -1453,6 +1454,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_facets_generation() {
|
fn test_facets_generation() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
|
let progress = Progress::default();
|
||||||
|
|
||||||
index
|
index
|
||||||
.add_documents(documents!([
|
.add_documents(documents!([
|
||||||
@@ -1507,7 +1509,7 @@ mod tests {
|
|||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
for (s, i) in [("zeroth", 0), ("first", 1), ("second", 2), ("third", 3)] {
|
for (s, i) in [("zeroth", 0), ("first", 1), ("second", 2), ("third", 3)] {
|
||||||
let mut search = crate::Search::new(&rtxn, &index);
|
let mut search = crate::Search::new(&rtxn, &index, &progress);
|
||||||
let filter = format!(r#""dog.race.bernese mountain" = {s}"#);
|
let filter = format!(r#""dog.race.bernese mountain" = {s}"#);
|
||||||
search.filter(crate::Filter::from_str(&filter).unwrap().unwrap());
|
search.filter(crate::Filter::from_str(&filter).unwrap().unwrap());
|
||||||
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
@@ -1545,7 +1547,7 @@ mod tests {
|
|||||||
|
|
||||||
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, &progress);
|
||||||
search.sort_criteria(vec![crate::AscDesc::Asc(crate::Member::Field(S(
|
search.sort_criteria(vec![crate::AscDesc::Asc(crate::Member::Field(S(
|
||||||
"dog.race.bernese mountain",
|
"dog.race.bernese mountain",
|
||||||
)))]);
|
)))]);
|
||||||
@@ -2911,7 +2913,6 @@ mod tests {
|
|||||||
]
|
]
|
||||||
*/
|
*/
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
|
|
||||||
// START OF BATCH
|
// START OF BATCH
|
||||||
|
|
||||||
println!("--- ENTERING BATCH 1");
|
println!("--- ENTERING BATCH 1");
|
||||||
@@ -3601,6 +3602,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn delete_words_exact_attributes() {
|
fn delete_words_exact_attributes() {
|
||||||
let index = TempIndex::new();
|
let index = TempIndex::new();
|
||||||
|
let progress = Progress::default();
|
||||||
|
|
||||||
index
|
index
|
||||||
.update_settings(|settings| {
|
.update_settings(|settings| {
|
||||||
@@ -3639,7 +3641,7 @@ mod tests {
|
|||||||
let words = index.words_fst(&txn).unwrap().into_stream().into_strs().unwrap();
|
let words = index.words_fst(&txn).unwrap().into_stream().into_strs().unwrap();
|
||||||
insta::assert_snapshot!(format!("{words:?}"), @r###"["hello"]"###);
|
insta::assert_snapshot!(format!("{words:?}"), @r###"["hello"]"###);
|
||||||
|
|
||||||
let mut s = Search::new(&txn, &index);
|
let mut s = Search::new(&txn, &index, &progress);
|
||||||
s.query("hello");
|
s.query("hello");
|
||||||
let crate::SearchResult { documents_ids, .. } = s.execute().unwrap();
|
let crate::SearchResult { documents_ids, .. } = s.execute().unwrap();
|
||||||
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0]");
|
insta::assert_snapshot!(format!("{documents_ids:?}"), @"[0]");
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ macro_rules! test_distinct {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.query(search::TEST_QUERY);
|
search.query(search::TEST_QUERY);
|
||||||
search.limit($limit);
|
search.limit($limit);
|
||||||
search.offset($offset);
|
search.offset($offset);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use either::{Either, Left, Right};
|
use either::{Either, Left, Right};
|
||||||
|
use milli::progress::Progress;
|
||||||
use milli::{Criterion, Filter, Search, SearchResult, TermsMatchingStrategy};
|
use milli::{Criterion, Filter, Search, SearchResult, TermsMatchingStrategy};
|
||||||
|
|
||||||
use Criterion::*;
|
use Criterion::*;
|
||||||
|
|
||||||
use crate::search::{self, EXTERNAL_DOCUMENTS_IDS};
|
use crate::search::{self, EXTERNAL_DOCUMENTS_IDS};
|
||||||
@@ -15,7 +17,8 @@ macro_rules! test_filter {
|
|||||||
let filter_conditions =
|
let filter_conditions =
|
||||||
Filter::from_array::<Vec<Either<Vec<&str>, &str>>, _>($filter).unwrap().unwrap();
|
Filter::from_array::<Vec<Either<Vec<&str>, &str>>, _>($filter).unwrap().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.query(search::TEST_QUERY);
|
search.query(search::TEST_QUERY);
|
||||||
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ fn test_phrase_search_with_stop_words_given_criteria(criteria: &[Criterion]) {
|
|||||||
// Phrase search containing stop words
|
// Phrase search containing stop words
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("\"the use of force\"");
|
search.query("\"the use of force\"");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
search.terms_matching_strategy(TermsMatchingStrategy::All);
|
search.terms_matching_strategy(TermsMatchingStrategy::All);
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ macro_rules! test_criterion {
|
|||||||
let index = search::setup_search_index_with_criteria(&criteria);
|
let index = search::setup_search_index_with_criteria(&criteria);
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.query(search::TEST_QUERY);
|
search.query(search::TEST_QUERY);
|
||||||
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
||||||
search.terms_matching_strategy($optional_word);
|
search.terms_matching_strategy($optional_word);
|
||||||
@@ -241,7 +242,8 @@ fn criteria_mixup() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.query(search::TEST_QUERY);
|
search.query(search::TEST_QUERY);
|
||||||
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
||||||
search.terms_matching_strategy(ALLOW_OPTIONAL_WORDS);
|
search.terms_matching_strategy(ALLOW_OPTIONAL_WORDS);
|
||||||
@@ -365,7 +367,8 @@ fn criteria_ascdesc() {
|
|||||||
|
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.limit(ASC_DESC_CANDIDATES_THRESHOLD + 1);
|
search.limit(ASC_DESC_CANDIDATES_THRESHOLD + 1);
|
||||||
|
|
||||||
let SearchResult { documents_ids, .. } = search.execute().unwrap();
|
let SearchResult { documents_ids, .. } = search.execute().unwrap();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use big_s::S;
|
use big_s::S;
|
||||||
|
use milli::progress::Progress;
|
||||||
use milli::Criterion::{Attribute, Exactness, Proximity, Typo, Words};
|
use milli::Criterion::{Attribute, Exactness, Proximity, Typo, Words};
|
||||||
use milli::{AscDesc, Error, Member, Search, TermsMatchingStrategy, UserError};
|
use milli::{AscDesc, Error, Member, Search, TermsMatchingStrategy, UserError};
|
||||||
|
|
||||||
@@ -11,7 +12,8 @@ fn sort_ranking_rule_missing() {
|
|||||||
let index = search::setup_search_index_with_criteria(&criteria);
|
let index = search::setup_search_index_with_criteria(&criteria);
|
||||||
let rtxn = index.read_txn().unwrap();
|
let rtxn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&rtxn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&rtxn, &index, &progress);
|
||||||
search.query(search::TEST_QUERY);
|
search.query(search::TEST_QUERY);
|
||||||
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
search.limit(EXTERNAL_DOCUMENTS_IDS.len());
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ fn test_typo_tolerance_one_typo() {
|
|||||||
{
|
{
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zeal");
|
search.query("zeal");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ fn test_typo_tolerance_one_typo() {
|
|||||||
let result = search.execute().unwrap();
|
let result = search.execute().unwrap();
|
||||||
assert_eq!(result.documents_ids.len(), 1);
|
assert_eq!(result.documents_ids.len(), 1);
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zean");
|
search.query("zean");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -49,7 +51,8 @@ fn test_typo_tolerance_one_typo() {
|
|||||||
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
||||||
|
|
||||||
// typo is now supported for 4 letters words
|
// typo is now supported for 4 letters words
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zean");
|
search.query("zean");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -68,7 +71,8 @@ fn test_typo_tolerance_two_typo() {
|
|||||||
{
|
{
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zealand");
|
search.query("zealand");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -77,7 +81,8 @@ fn test_typo_tolerance_two_typo() {
|
|||||||
let result = search.execute().unwrap();
|
let result = search.execute().unwrap();
|
||||||
assert_eq!(result.documents_ids.len(), 1);
|
assert_eq!(result.documents_ids.len(), 1);
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zealemd");
|
search.query("zealemd");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -95,7 +100,8 @@ fn test_typo_tolerance_two_typo() {
|
|||||||
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
||||||
|
|
||||||
// typo is now supported for 4 letters words
|
// typo is now supported for 4 letters words
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zealemd");
|
search.query("zealemd");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -164,7 +170,8 @@ fn test_typo_disabled_on_word() {
|
|||||||
{
|
{
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zealand");
|
search.query("zealand");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -184,7 +191,8 @@ fn test_typo_disabled_on_word() {
|
|||||||
builder.set_exact_words(exact_words);
|
builder.set_exact_words(exact_words);
|
||||||
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("zealand");
|
search.query("zealand");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
@@ -203,7 +211,8 @@ fn test_disable_typo_on_attribute() {
|
|||||||
{
|
{
|
||||||
let txn = index.read_txn().unwrap();
|
let txn = index.read_txn().unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
// typo in `antebel(l)um`
|
// typo in `antebel(l)um`
|
||||||
search.query("antebelum");
|
search.query("antebelum");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
@@ -222,7 +231,8 @@ fn test_disable_typo_on_attribute() {
|
|||||||
builder.set_exact_attributes(vec!["description".to_string()].into_iter().collect());
|
builder.set_exact_attributes(vec!["description".to_string()].into_iter().collect());
|
||||||
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
builder.execute(&|| false, &Progress::default(), Default::default()).unwrap();
|
||||||
|
|
||||||
let mut search = Search::new(&txn, &index);
|
let progress = Progress::default();
|
||||||
|
let mut search = Search::new(&txn, &index, &progress);
|
||||||
search.query("antebelum");
|
search.query("antebelum");
|
||||||
search.limit(10);
|
search.limit(10);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user