diff --git a/Cargo.toml b/Cargo.toml index 84a1bea6..16560fd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tantivy" -version = "0.17.0" +version = "0.17.1" readme = "README.md" authors = ["Damir Jelić "] edition = "2018" @@ -11,7 +11,7 @@ name = "tantivy" crate-type = ["cdylib"] [build-dependencies] -pyo3-build-config = "0.16.3" +pyo3-build-config = "0.15.0" [dependencies] chrono = "0.4.19" @@ -19,7 +19,9 @@ tantivy = "0.17" itertools = "0.10.3" futures = "0.3.21" serde_json = "1.0.64" +serde = "1.0" +serde_derive = "1.0" [dependencies.pyo3] -version = "0.16.3" +version = "0.15.0" features = ["extension-module"] diff --git a/README.md b/README.md index 3fe76192..2f291277 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ Running the tests is done using: make test +Building python wheel + pip install maturin + maturin build + # Usage The Python bindings have a similar API to Tantivy. To create a index first a schema diff --git a/src/lib.rs b/src/lib.rs index 0593715c..5280968b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ use index::Index; use schema::Schema; use schemabuilder::SchemaBuilder; use searcher::{DocAddress, Searcher}; +use query::Query; /// Python bindings for the search engine library Tantivy. /// @@ -75,6 +76,7 @@ fn tantivy(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/src/query.rs b/src/query.rs index 40e43829..b1864c8a 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1,5 +1,8 @@ +use crate::to_pyerr; use pyo3::prelude::*; +use std::ops::Bound; use tantivy as tv; +use tv::schema::{Field, Term}; /// Tantivy's Query #[pyclass] @@ -15,7 +18,90 @@ impl Query { #[pymethods] impl Query { + #[staticmethod] + fn term(field_id: u32, text: &str) -> Query { + let term = Term::from_field_text(Field::from_field_id(field_id), text); + Query { + inner: Box::new(tv::query::TermQuery::new( + term, + tv::schema::IndexRecordOption::Basic, + )), + } + } + + #[staticmethod] + fn fuzzy_term(field_id: u32, distance: u8, text: &str) -> Query { + let ftq = tv::query::FuzzyTermQuery::new( + Term::from_field_text(Field::from_field_id(field_id), text), + distance, + true, + ); + Query { + inner: (Box::new(ftq)), + } + } + + #[staticmethod] + fn regex(field_id: u32, pattern: &str) -> PyResult { + let rq = tv::query::RegexQuery::from_pattern( + pattern, + Field::from_field_id(field_id), + ) + .map_err(to_pyerr)?; + Ok(Query { + inner: Box::new(rq), + }) + } + + #[staticmethod] + fn phrase(field_id: u32, words: Vec<&str>) -> Query { + let terms = words + .iter() + .map(|&w| Term::from_field_text(Field::from_field_id(field_id), w)) + .collect::>(); + Query { + inner: Box::new(tv::query::PhraseQuery::new(terms)), + } + } + + #[staticmethod] + fn boost(q: &Query, boost: f32) -> Query { + let bq = tv::query::BoostQuery::new(q.get().box_clone(), boost); + Query { + inner: Box::new(bq), + } + } + + #[staticmethod] + fn and_q(qs : Vec>) -> Query { + Query { + inner: Box::new(tv::query::BooleanQuery::intersection( + qs.iter().map(|q| q.get().box_clone()).collect::>() + )) + } + } + + #[staticmethod] + fn or_q(qs : Vec>) -> Query { + Query { + inner: Box::new(tv::query::BooleanQuery::union( + qs.iter().map(|q| q.get().box_clone()).collect::>() + )) + } + } + + #[staticmethod] + fn range_q(field_id: u32, left: &str, right: &str) -> Query { + Query { + inner: Box::new(tv::query::RangeQuery::new_str_bounds( + Field::from_field_id(field_id), + Bound::Included(left), + Bound::Included(right), + )), + } + } + fn __repr__(&self) -> PyResult { - Ok(format!("Query({:?})", self.get())) + Ok(format!("{:#?}", self.get())) } }