2010-02-08 15:30:06 +02:00
/ *
2014-01-06 22:48:02 +01:00
* Licensed to Elasticsearch under one or more contributor
* license agreements . See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership . Elasticsearch licenses this file to you under
* the Apache License , Version 2 . 0 ( the " License " ) ; you may
* not use this file except in compliance with the License .
* You may obtain a copy of the License at
2010-02-08 15:30:06 +02:00
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing ,
* software distributed under the License is distributed on an
* " AS IS " BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND , either express or implied . See the License for the
* specific language governing permissions and limitations
* under the License .
* /
2011-06-03 04:32:27 +03:00
package org.elasticsearch.index.query ;
2010-02-08 15:30:06 +02:00
import org.apache.lucene.search.Query ;
import org.apache.lucene.search.TermRangeQuery ;
2010-06-15 16:51:38 +03:00
import org.elasticsearch.common.inject.Inject ;
2014-07-31 16:22:03 +02:00
import org.elasticsearch.common.joda.DateMathParser ;
2012-12-29 00:14:46 -08:00
import org.elasticsearch.common.lucene.BytesRefs ;
2010-06-15 16:51:38 +03:00
import org.elasticsearch.common.xcontent.XContentParser ;
2014-07-31 16:22:03 +02:00
import org.elasticsearch.index.mapper.FieldMapper ;
2010-02-08 15:30:06 +02:00
import org.elasticsearch.index.mapper.MapperService ;
2014-07-31 16:22:03 +02:00
import org.elasticsearch.index.mapper.core.DateFieldMapper ;
import org.joda.time.DateTimeZone ;
2010-02-08 15:30:06 +02:00
import java.io.IOException ;
2011-12-06 02:42:25 +02:00
import static org.elasticsearch.index.query.support.QueryParsers.wrapSmartNameQuery ;
2010-02-08 15:30:06 +02:00
/ * *
2011-12-06 02:42:25 +02:00
*
2010-02-08 15:30:06 +02:00
* /
2011-06-03 06:02:18 +03:00
public class RangeQueryParser implements QueryParser {
2010-02-08 15:30:06 +02:00
public static final String NAME = " range " ;
2011-12-06 02:42:25 +02:00
@Inject
public RangeQueryParser ( ) {
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public String [ ] names ( ) {
2010-04-04 23:59:15 +03:00
return new String [ ] { NAME } ;
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public Query parse ( QueryParseContext parseContext ) throws IOException , QueryParsingException {
2010-04-29 00:05:55 +03:00
XContentParser parser = parseContext . parser ( ) ;
2010-02-08 15:30:06 +02:00
2010-04-29 00:05:55 +03:00
XContentParser . Token token = parser . nextToken ( ) ;
2012-01-26 13:53:37 +02:00
if ( token ! = XContentParser . Token . FIELD_NAME ) {
throw new QueryParsingException ( parseContext . index ( ) , " [range] query malformed, no field to indicate field name " ) ;
}
2010-04-29 00:05:55 +03:00
String fieldName = parser . currentName ( ) ;
2012-01-26 13:53:37 +02:00
token = parser . nextToken ( ) ;
if ( token ! = XContentParser . Token . START_OBJECT ) {
throw new QueryParsingException ( parseContext . index ( ) , " [range] query malformed, after field missing start object " ) ;
}
2010-02-08 15:30:06 +02:00
2012-12-29 00:14:46 -08:00
Object from = null ;
Object to = null ;
2010-02-08 15:30:06 +02:00
boolean includeLower = true ;
boolean includeUpper = true ;
2014-07-31 16:22:03 +02:00
DateTimeZone timeZone = null ;
2010-02-08 15:30:06 +02:00
float boost = 1 . 0f ;
2013-08-28 10:42:33 +02:00
String queryName = null ;
2010-02-08 15:30:06 +02:00
String currentFieldName = null ;
2010-04-29 00:05:55 +03:00
while ( ( token = parser . nextToken ( ) ) ! = XContentParser . Token . END_OBJECT ) {
if ( token = = XContentParser . Token . FIELD_NAME ) {
currentFieldName = parser . currentName ( ) ;
2010-02-08 15:30:06 +02:00
} else {
if ( " from " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
from = parser . objectBytes ( ) ;
2010-02-08 15:30:06 +02:00
} else if ( " to " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
to = parser . objectBytes ( ) ;
2010-04-14 11:48:33 +03:00
} else if ( " include_lower " . equals ( currentFieldName ) | | " includeLower " . equals ( currentFieldName ) ) {
2010-04-29 00:05:55 +03:00
includeLower = parser . booleanValue ( ) ;
2010-04-14 11:48:33 +03:00
} else if ( " include_upper " . equals ( currentFieldName ) | | " includeUpper " . equals ( currentFieldName ) ) {
2010-04-29 00:05:55 +03:00
includeUpper = parser . booleanValue ( ) ;
2010-02-08 15:30:06 +02:00
} else if ( " boost " . equals ( currentFieldName ) ) {
2010-04-29 00:05:55 +03:00
boost = parser . floatValue ( ) ;
2010-04-04 22:14:45 +03:00
} else if ( " gt " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
from = parser . objectBytes ( ) ;
2010-04-04 22:14:45 +03:00
includeLower = false ;
2010-04-14 11:48:33 +03:00
} else if ( " gte " . equals ( currentFieldName ) | | " ge " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
from = parser . objectBytes ( ) ;
2010-04-04 22:14:45 +03:00
includeLower = true ;
} else if ( " lt " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
to = parser . objectBytes ( ) ;
2010-04-04 22:14:45 +03:00
includeUpper = false ;
2010-04-14 11:48:33 +03:00
} else if ( " lte " . equals ( currentFieldName ) | | " le " . equals ( currentFieldName ) ) {
2012-12-29 00:14:46 -08:00
to = parser . objectBytes ( ) ;
2010-04-04 22:14:45 +03:00
includeUpper = true ;
2014-07-31 16:22:03 +02:00
} else if ( " time_zone " . equals ( currentFieldName ) | | " timeZone " . equals ( currentFieldName ) ) {
timeZone = DateMathParser . parseZone ( parser . text ( ) ) ;
2013-08-28 10:42:33 +02:00
} else if ( " _name " . equals ( currentFieldName ) ) {
queryName = parser . text ( ) ;
2012-01-26 13:53:37 +02:00
} else {
throw new QueryParsingException ( parseContext . index ( ) , " [range] query does not support [ " + currentFieldName + " ] " ) ;
2010-02-08 15:30:06 +02:00
}
}
}
2010-02-20 01:42:17 +02:00
// move to the next end object, to close the field name
2010-04-29 00:05:55 +03:00
token = parser . nextToken ( ) ;
2012-01-26 13:53:37 +02:00
if ( token ! = XContentParser . Token . END_OBJECT ) {
throw new QueryParsingException ( parseContext . index ( ) , " [range] query malformed, does not end with an object " ) ;
}
2010-02-20 01:42:17 +02:00
2010-02-08 15:30:06 +02:00
Query query = null ;
MapperService . SmartNameFieldMappers smartNameFieldMappers = parseContext . smartFieldMappers ( fieldName ) ;
if ( smartNameFieldMappers ! = null ) {
2010-02-16 21:47:56 +02:00
if ( smartNameFieldMappers . hasMapper ( ) ) {
2014-07-31 16:22:03 +02:00
FieldMapper mapper = smartNameFieldMappers . mapper ( ) ;
if ( mapper instanceof DateFieldMapper ) {
if ( ( from instanceof Number | | to instanceof Number ) & & timeZone ! = null ) {
throw new QueryParsingException ( parseContext . index ( ) , " [range] time_zone when using ms since epoch format as it's UTC based can not be applied to [ " + fieldName + " ] " ) ;
}
query = ( ( DateFieldMapper ) mapper ) . rangeQuery ( from , to , includeLower , includeUpper , timeZone , parseContext ) ;
} else {
if ( timeZone ! = null ) {
throw new QueryParsingException ( parseContext . index ( ) , " [range] time_zone can not be applied to non date field [ " + fieldName + " ] " ) ;
}
//LUCENE 4 UPGRADE Mapper#rangeQuery should use bytesref as well?
query = mapper . rangeQuery ( from , to , includeLower , includeUpper , parseContext ) ;
}
2010-02-08 15:30:06 +02:00
}
}
if ( query = = null ) {
2012-12-29 00:14:46 -08:00
query = new TermRangeQuery ( fieldName , BytesRefs . toBytesRef ( from ) , BytesRefs . toBytesRef ( to ) , includeLower , includeUpper ) ;
2010-02-08 15:30:06 +02:00
}
query . setBoost ( boost ) ;
2013-08-28 10:42:33 +02:00
query = wrapSmartNameQuery ( query , smartNameFieldMappers , parseContext ) ;
if ( queryName ! = null ) {
parseContext . addNamedQuery ( queryName , query ) ;
}
return query ;
2010-02-08 15:30:06 +02:00
}
2014-07-31 16:22:03 +02:00
}