diff --git a/server/src/lib.rs b/server/src/lib.rs index 81445c2..bd6c5d1 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -605,7 +605,7 @@ fn compute_offset_limit( } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Query { pub unread_only: bool, pub tags: Vec, diff --git a/server/src/tantivy.rs b/server/src/tantivy.rs index e487416..11b7226 100644 --- a/server/src/tantivy.rs +++ b/server/src/tantivy.rs @@ -57,7 +57,7 @@ impl TantivyConnection { ); let start_time = std::time::Instant::now(); - let (searcher, _query) = self.searcher_and_query("")?; + let (searcher, _query) = self.searcher_and_query(&Query::default())?; let docs = searcher.search(&AllQuery, &DocSetCollector)?; let uid = self.get_index()?.schema().get_field("uid")?; let t_uids: Vec<_> = docs @@ -187,7 +187,7 @@ impl TantivyConnection { } fn searcher_and_query( &self, - term: &str, + query: &Query, ) -> Result<(Searcher, Box), ServerError> { let index = self.get_index()?; let reader = index.reader()?; @@ -197,20 +197,41 @@ impl TantivyConnection { let summary = schema.get_field("summary")?; let query_parser = QueryParser::for_index(&index, vec![title, summary]); // Tantivy uses '*' to match all docs, not empty string + let term = &query.remainder.join(" "); let term = if term.is_empty() { "*" } else { term }; - info!("query_parser('{term}')"); - let query = query_parser.parse_query(&term)?; - Ok((searcher, query)) + + let tantivy_query = query_parser.parse_query(&term)?; + + let tag = self.get_index()?.schema().get_field("tag")?; + let is_read = self.get_index()?.schema().get_field("is_read")?; + let mut terms = vec![(Occur::Must, tantivy_query)]; + for t in &query.tags { + let facet = Facet::from(&format!("/{t}")); + let facet_term = Term::from_facet(tag, &facet); + let facet_term_query = Box::new(TermQuery::new(facet_term, IndexRecordOption::Basic)); + terms.push((Occur::Must, facet_term_query)); + } + if query.unread_only { + info!("searching for unread only"); + let term = Term::from_field_bool(is_read, false); + terms.push(( + Occur::Must, + Box::new(TermQuery::new(term, IndexRecordOption::Basic)), + )); + } + let search_query = BooleanQuery::new(terms); + Ok((searcher, Box::new(search_query))) } pub async fn count(&self, query: &Query) -> Result { if !is_tantivy_query(query) { return Ok(0); } + info!("tantivy::count {query:?}"); use tantivy::collector::Count; let term = query.remainder.join(" "); - let (searcher, query) = self.searcher_and_query(&term)?; + let (searcher, query) = self.searcher_and_query(&query)?; Ok(searcher.search(&query, &Count)?) } pub async fn search( @@ -233,27 +254,8 @@ impl TantivyConnection { limit = limit + 1; } - let term = query.remainder.join(" "); - let (searcher, tantivy_query) = self.searcher_and_query(&term)?; - let tag = self.get_index()?.schema().get_field("tag")?; - let is_read = self.get_index()?.schema().get_field("is_read")?; - let mut terms = vec![(Occur::Must, tantivy_query)]; - for t in &query.tags { - let facet = Facet::from(&format!("/{t}")); - let facet_term = Term::from_facet(tag, &facet); - let facet_term_query = Box::new(TermQuery::new(facet_term, IndexRecordOption::Basic)); - terms.push((Occur::Must, facet_term_query)); - } - if query.unread_only { - info!("searching for unread only"); - let term = Term::from_field_bool(is_read, false); - terms.push(( - Occur::Must, - Box::new(TermQuery::new(term, IndexRecordOption::Basic)), - )); - } - let search_query = BooleanQuery::new(terms); - info!("Tantivy::search(term '{term}', off {offset}, lim {limit}, search_query {search_query:?})"); + let (searcher, search_query) = self.searcher_and_query(&query)?; + info!("Tantivy::search(query '{query:?}', off {offset}, lim {limit}, search_query {search_query:?})"); let top_docs = searcher.search( &search_query, &TopDocs::with_limit(limit as usize)