fix: query string time zone not working

If you define exactly the same date range query using either `DATE+0200` notation or `DATE` and set `timezone: +0200`, elasticsearch gives back different results:

```
DELETE foo
PUT /foo
{
  "mapping": {
    "tweets": {
      "properties": {
        "tweet_date": {
          "type": "date"
        }
      }
    }
  }
}

POST /foo/tweets/1/
{
  "tweet_date": "2015-04-05T23:00:00+0000"
}
POST /foo/tweets/2/
{
  "tweet_date": "2015-04-06T00:00:00+0000"
}

GET /foo/tweets/_search?pretty
{
    "query": {
        "query_string": {
            "query": "tweet_date:[2015-04-06T00:00:00+0200 TO 2015-04-06T23:00:00+0200]"
        }
    }
}
GET /foo/tweets/_search?pretty
{
    "query": {
        "query_string": {
            "query": "tweet_date:[2015-04-06T00:00:00 TO 2015-04-06T23:00:00]",
            "time_zone": "+0200"
        }
    }
}
```

This PR fixes it and will also allow us to add the same feature to simple_query_string as well in another PR.

Closes #10477.

(cherry picked from commit 880f4a0)
This commit is contained in:
David Pilato 2015-04-29 18:10:02 +02:00
parent d4463602f6
commit 3c3e9b63a7
2 changed files with 47 additions and 4 deletions

View File

@ -39,6 +39,7 @@ import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.support.QueryParsers;
@ -131,9 +132,6 @@ public class MapperQueryParser extends QueryParser {
setFuzzyMinSim(settings.fuzzyMinSim());
setFuzzyPrefixLength(settings.fuzzyPrefixLength());
setLocale(settings.locale());
if (settings.timeZone() != null) {
setTimeZone(settings.timeZone().toTimeZone());
}
this.analyzeWildcard = settings.analyzeWildcard();
}
@ -377,7 +375,14 @@ public class MapperQueryParser extends QueryParser {
}
try {
return currentMapper.rangeQuery(part1, part2, startInclusive, endInclusive, parseContext);
Query rangeQuery;
if (currentMapper instanceof DateFieldMapper && settings.timeZone() != null) {
DateFieldMapper dateFieldMapper = (DateFieldMapper) this.currentMapper;
rangeQuery = dateFieldMapper.rangeQuery(part1, part2, startInclusive, endInclusive, settings.timeZone(), null, parseContext);
} else {
rangeQuery = currentMapper.rangeQuery(part1, part2, startInclusive, endInclusive, parseContext);
}
return rangeQuery;
} catch (RuntimeException e) {
if (settings.lenient()) {
return null;

View File

@ -587,6 +587,44 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
assertHitCount(searchResponse, 1l);
}
@Test // https://github.com/elasticsearch/elasticsearch/issues/10477
public void testDateRangeInQueryStringWithTimeZone_10477() {
//the mapping needs to be provided upfront otherwise we are not sure how many failures we get back
//as with dynamic mappings some shards might be lacking behind and parse a different query
assertAcked(prepareCreate("test").addMapping(
"type", "past", "type=date"
));
ensureGreen();
client().prepareIndex("test", "type", "1").setSource("past", "2015-04-05T23:00:00+0000").get();
client().prepareIndex("test", "type", "2").setSource("past", "2015-04-06T00:00:00+0000").get();
refresh();
// Timezone set with dates
SearchResponse searchResponse = client().prepareSearch()
.setQuery(queryStringQuery("past:[2015-04-06T00:00:00+0200 TO 2015-04-06T23:00:00+0200]"))
.get();
assertHitCount(searchResponse, 2l);
// Same timezone set with time_zone
searchResponse = client().prepareSearch()
.setQuery(queryStringQuery("past:[2015-04-06T00:00:00 TO 2015-04-06T23:00:00]").timeZone("+0200"))
.get();
assertHitCount(searchResponse, 2l);
// We set a timezone which will give no result
searchResponse = client().prepareSearch()
.setQuery(queryStringQuery("past:[2015-04-06T00:00:00-0200 TO 2015-04-06T23:00:00-0200]"))
.get();
assertHitCount(searchResponse, 0l);
// Same timezone set with time_zone but another timezone is set directly within dates which has the precedence
searchResponse = client().prepareSearch()
.setQuery(queryStringQuery("past:[2015-04-06T00:00:00-0200 TO 2015-04-06T23:00:00-0200]").timeZone("+0200"))
.get();
assertHitCount(searchResponse, 0l);
}
@Test
public void typeFilterTypeIndexedTests() throws Exception {
typeFilterTests("not_analyzed");