mirror of
https://github.com/quickwit-oss/tantivy.git
synced 2026-05-21 18:50:42 +00:00
Query parser.
This commit is contained in:
@@ -14,6 +14,7 @@ use postings::DocSet;
|
||||
use query::MultiTermScorer;
|
||||
use std::iter;
|
||||
|
||||
|
||||
pub struct MultiTermQuery {
|
||||
terms: Vec<Term>,
|
||||
}
|
||||
|
||||
@@ -1,20 +1,81 @@
|
||||
use combine::primitives::Stream;
|
||||
use combine::*;
|
||||
use collector::Collector;
|
||||
use std::io;
|
||||
use core::searcher::Searcher;
|
||||
use common::TimerTree;
|
||||
use query::{Query, MultiTermQuery};
|
||||
use schema::Schema;
|
||||
use schema::{Term, Field};
|
||||
|
||||
|
||||
pub struct QueryParser
|
||||
{
|
||||
// split_ptn: Regex,
|
||||
pub enum ParsingError {
|
||||
SyntaxError,
|
||||
FieldDoesNotExist(String),
|
||||
}
|
||||
|
||||
pub struct QueryParser {
|
||||
schema: Schema,
|
||||
default_field: Field,
|
||||
}
|
||||
|
||||
pub enum StandardQuery {
|
||||
MultiTerm(MultiTermQuery),
|
||||
}
|
||||
|
||||
impl Query for StandardQuery {
|
||||
fn search<C: Collector>(&self, searcher: &Searcher, collector: &mut C) -> io::Result<TimerTree> {
|
||||
match *self {
|
||||
StandardQuery::MultiTerm(ref q) => {
|
||||
q.search(searcher, collector)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl QueryParser {
|
||||
pub fn new() -> QueryParser {
|
||||
QueryParser {}
|
||||
pub fn new(schema: Schema,
|
||||
default_field: Field) -> QueryParser {
|
||||
QueryParser {
|
||||
schema: schema,
|
||||
default_field: default_field,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn parse_query() {
|
||||
// TODO check that the term is str.
|
||||
// we only support str field for the moment
|
||||
fn transform_literal(&self, literal: Literal) -> Result<Term, ParsingError> {
|
||||
match literal {
|
||||
Literal::DefaultField(val) => {
|
||||
Ok(Term::from_field_text(self.default_field, &val))
|
||||
},
|
||||
Literal::WithField(field_name, val) => {
|
||||
match self.schema.get_field(&field_name) {
|
||||
Some(field) => {
|
||||
Ok(Term::from_field_text(field, &val))
|
||||
}
|
||||
None => {
|
||||
Err(ParsingError::FieldDoesNotExist(field_name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
pub fn parse_query(&self, query: &str) -> Result<StandardQuery, ParsingError> {
|
||||
match parser(query_language).parse(query) {
|
||||
Ok(literals) => {
|
||||
let terms_result: Result<Vec<Term>, ParsingError> = literals.0.into_iter()
|
||||
.map(|literal| self.transform_literal(literal))
|
||||
.collect();
|
||||
terms_result
|
||||
.map(MultiTermQuery::new)
|
||||
.map(StandardQuery::MultiTerm)
|
||||
}
|
||||
Err(_) => {
|
||||
Err(ParsingError::SyntaxError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +85,7 @@ pub enum Literal {
|
||||
DefaultField(String),
|
||||
}
|
||||
|
||||
pub fn query_language<I>(input: State<I>) -> ParseResult<Vec<Literal>, I>
|
||||
where I: Stream<Item=char>
|
||||
pub fn query_language(input: State<&str>) -> ParseResult<Vec<Literal>, &str>
|
||||
{
|
||||
let literal = || {
|
||||
let term_val = || {
|
||||
@@ -33,14 +93,12 @@ pub fn query_language<I>(input: State<I>) -> ParseResult<Vec<Literal>, I>
|
||||
let phrase =
|
||||
(char('"'), many1(satisfy(|c| c != '"')), char('"'),)
|
||||
.map(|(_, s, _)| s);
|
||||
|
||||
phrase.or(word)
|
||||
};
|
||||
|
||||
let field = many1(letter());
|
||||
let term_query = (field, char(':'), term_val())
|
||||
.map(|(field,_, value)| Literal::WithField(field, value));
|
||||
|
||||
let term_default_field = term_val().map(|w| Literal::DefaultField(w));
|
||||
try(term_query)
|
||||
.or(term_default_field)
|
||||
|
||||
Reference in New Issue
Block a user