From 4e4937ebb6242bbe2f4cab307a015b5c905e2fe4 Mon Sep 17 00:00:00 2001 From: Paul Masurel Date: Thu, 28 Jul 2016 21:29:27 +0900 Subject: [PATCH] Query parser. --- src/query/multi_term_query.rs | 1 + src/query/query_parser.rs | 84 +++++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/query/multi_term_query.rs b/src/query/multi_term_query.rs index 99e455f8d..e7a0f393b 100644 --- a/src/query/multi_term_query.rs +++ b/src/query/multi_term_query.rs @@ -14,6 +14,7 @@ use postings::DocSet; use query::MultiTermScorer; use std::iter; + pub struct MultiTermQuery { terms: Vec, } diff --git a/src/query/query_parser.rs b/src/query/query_parser.rs index 3e8329239..e3a433134 100644 --- a/src/query/query_parser.rs +++ b/src/query/query_parser.rs @@ -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(&self, searcher: &Searcher, collector: &mut C) -> io::Result { + 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 { + 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 { + match parser(query_language).parse(query) { + Ok(literals) => { + let terms_result: Result, 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(input: State) -> ParseResult, I> - where I: Stream +pub fn query_language(input: State<&str>) -> ParseResult, &str> { let literal = || { let term_val = || { @@ -33,14 +93,12 @@ pub fn query_language(input: State) -> ParseResult, 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)