Add support for placeholder search for empty queries

This commit is contained in:
Kerollmops 2020-10-06 14:52:05 +02:00 committed by Clément Renault
parent 433d9bbc6e
commit a00f5850ee
No known key found for this signature in database
GPG Key ID: 92ADA4E935E71FA4
4 changed files with 33 additions and 17 deletions

View File

@ -74,3 +74,9 @@ $('#docs-count').text(function(index, text) {
$('#db-size').text(function(index, text) { $('#db-size').text(function(index, text) {
return filesize(parseInt(text)) return filesize(parseInt(text))
}); });
// We trigger the input when we load the script, this way
// we execute a placeholder search when the input is empty.
$(window).on('load', function () {
$('#search').trigger('input');
});

View File

@ -172,7 +172,7 @@ async fn main() -> anyhow::Result<()> {
#[derive(Deserialize)] #[derive(Deserialize)]
struct QueryBody { struct QueryBody {
query: String, query: Option<String>,
} }
let env_cloned = env.clone(); let env_cloned = env.clone();
@ -184,10 +184,12 @@ async fn main() -> anyhow::Result<()> {
let before_search = Instant::now(); let before_search = Instant::now();
let rtxn = env_cloned.read_txn().unwrap(); let rtxn = env_cloned.read_txn().unwrap();
let SearchResult { found_words, documents_ids } = index.search(&rtxn) let mut search = index.search(&rtxn);
.query(query.query) if let Some(query) = query.query {
.execute() search.query(query);
.unwrap(); }
let SearchResult { found_words, documents_ids } = search.execute().unwrap();
let body = match index.headers(&rtxn).unwrap() { let body = match index.headers(&rtxn).unwrap() {
Some(headers) => { Some(headers) => {

View File

@ -14,6 +14,7 @@ use csv::StringRecord;
use fxhash::{FxHasher32, FxHasher64}; use fxhash::{FxHasher32, FxHasher64};
use heed::types::*; use heed::types::*;
use heed::{PolyDatabase, Database}; use heed::{PolyDatabase, Database};
use roaring::RoaringBitmap;
pub use self::search::{Search, SearchResult}; pub use self::search::{Search, SearchResult};
pub use self::criterion::{Criterion, default_criteria}; pub use self::criterion::{Criterion, default_criteria};
@ -61,6 +62,10 @@ impl Index {
}) })
} }
pub fn documents_ids(&self, rtxn: &heed::RoTxn) -> anyhow::Result<Option<RoaringBitmap>> {
Ok(self.main.get::<_, Str, RoaringBitmapCodec>(rtxn, DOCUMENTS_IDS_KEY)?)
}
pub fn put_headers(&self, wtxn: &mut heed::RwTxn, headers: &StringRecord) -> heed::Result<()> { pub fn put_headers(&self, wtxn: &mut heed::RwTxn, headers: &StringRecord) -> heed::Result<()> {
self.main.put::<_, Str, CsvStringRecordCodec>(wtxn, HEADERS_KEY, headers) self.main.put::<_, Str, CsvStringRecordCodec>(wtxn, HEADERS_KEY, headers)
} }
@ -114,10 +119,11 @@ impl Index {
} }
/// Returns the number of documents indexed in the database. /// Returns the number of documents indexed in the database.
pub fn number_of_documents<'t>(&self, rtxn: &'t heed::RoTxn) -> anyhow::Result<usize> { pub fn number_of_documents(&self, rtxn: &heed::RoTxn) -> anyhow::Result<usize> {
let docids = self.main.get::<_, Str, RoaringBitmapCodec>(rtxn, DOCUMENTS_IDS_KEY)? match self.documents_ids(rtxn)? {
.with_context(|| format!("Could not find the list of documents ids"))?; Some(docids) => Ok(docids.len() as usize),
Ok(docids.len() as usize) None => Ok(0),
}
} }
pub fn search<'a>(&'a self, rtxn: &'a heed::RoTxn) -> Search<'a> { pub fn search<'a>(&'a self, rtxn: &'a heed::RoTxn) -> Search<'a> {

View File

@ -141,16 +141,18 @@ impl<'a> Search<'a> {
}; };
// Construct the DFAs related to the query words. // Construct the DFAs related to the query words.
// TODO do a placeholder search when query string isn't present. let dfas = match self.query.as_deref().map(Self::generate_query_dfas) {
let dfas = match &self.query { Some(dfas) if !dfas.is_empty() => dfas,
Some(q) => Self::generate_query_dfas(q), _ => {
None => return Ok(Default::default()), // If the query is not set or results in no DFAs we return a placeholder.
let documents_ids = match self.index.documents_ids(self.rtxn)? {
Some(docids) => docids.iter().take(limit).collect(),
None => Vec::new(),
};
return Ok(SearchResult { documents_ids, ..Default::default() })
},
}; };
if dfas.is_empty() {
return Ok(Default::default());
}
let derived_words = self.fetch_words_docids(&fst, dfas)?; let derived_words = self.fetch_words_docids(&fst, dfas)?;
let candidates = Self::compute_candidates(&derived_words); let candidates = Self::compute_candidates(&derived_words);