Query parser.

This commit is contained in:
Paul Masurel
2016-07-28 21:29:27 +09:00
parent 5f64e1ec9c
commit 4e4937ebb6
2 changed files with 72 additions and 13 deletions

View File

@@ -14,6 +14,7 @@ use postings::DocSet;
use query::MultiTermScorer;
use std::iter;
pub struct MultiTermQuery {
terms: Vec<Term>,
}

View File

@@ -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)