Skip to content

datehistogram sometimes ignores format when searching on multiple indexes #31760

Closed
@plaarakkers

Description

@plaarakkers

Elasticsearch version (Version: 6.3.0 (docker image based on docker.elastic.co/elasticsearch/elasticsearch:6.3.0)):

Plugins installed: []

JVM version (client build 1.8.0_171-b11):

OS version (Linux 4.15.0-23-generic):

Description of the problem including expected versus actual behavior:

The date histogram ignores the format of the aggregation or date field
if the search is performed on multiple indexes where the alphabetically first index does not contain the date field. This results in an unexpected value for the key_as_string in the bucket

Steps to reproduce:
I created a unit test to reproduce the issue. This uses the following mappings:
searchIndexWithDateField.json

{
  "doc": {
    "dynamic": "strict",
    "properties": {
      "title": {
        "type": "keyword",
        "index": false
      },
      "dateField": {
        "type": "date",
        "format": "yyyy-MM-dd"
      }
    }
  }
}

searchIndexWithoutDateField.json

{
  "doc": {
    "dynamic": "strict",
    "properties": {
      "title": {
        "type": "keyword",
        "index": false
      }
    }
  }
}

The unit test itself uses version 6.3.0 for the java client maven dependencies:

package nl.gellygwin;

import org.apache.commons.io.IOUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class DateHistogramFormatTest {

    private static final String INDEX_TYPE = "doc";

    private static final String AGGREGATION_NAME = "dateTest";

    private static final String DATE_FIELD = "dateField";

    private TransportClient transportClient;

    @Before
    public void before() throws UnknownHostException {
        transportClient = new PreBuiltTransportClient(Settings.builder()
                .put("cluster.name", "docker-cluster")
                .build())
                .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));

        transportClient.admin().indices().prepareDelete("_all")
                .get();
    }

    @Test
    public void testDateFieldFormatIncorrect() throws IOException {
        //setup indexes
        final String indexNameWithDateField = "b";
        final String indexNameWithoutDateField = "a";

        setup(indexNameWithDateField, indexNameWithoutDateField);

        final SearchResponse searchResponse = transportClient.prepareSearch("*")
                .addAggregation(AggregationBuilders.dateHistogram(AGGREGATION_NAME)
                        .dateHistogramInterval(DateHistogramInterval.MONTH)
                        .field(DATE_FIELD))
                .get();

        System.out.println("testDateFieldFormatIncorrect: " + searchResponse.getAggregations().get(AGGREGATION_NAME));
    }

    @Test
    public void testDateFieldFormatCorrect() throws IOException {
        //setup indexes
        final String indexNameWithDateField = "a";
        final String indexNameWithoutDateField = "b";

        setup(indexNameWithDateField, indexNameWithoutDateField);

        final SearchResponse searchResponse = transportClient.prepareSearch("*")
                .addAggregation(AggregationBuilders.dateHistogram(AGGREGATION_NAME)
                        .dateHistogramInterval(DateHistogramInterval.MONTH)
                        .field(DATE_FIELD))
                .get();

        System.out.println("testDateFieldFormatCorrect: " + searchResponse.getAggregations().get(AGGREGATION_NAME));
    }

    @Test
    public void testAggregationFormatIncorrect() throws IOException {
        //setup indexes
        final String indexNameWithDateField = "b";
        final String indexNameWithoutDateField = "a";

        setup(indexNameWithDateField, indexNameWithoutDateField);

        final SearchResponse searchResponse = transportClient.prepareSearch("*")
                .addAggregation(AggregationBuilders.dateHistogram(AGGREGATION_NAME)
                        .dateHistogramInterval(DateHistogramInterval.MONTH)
                        .format("yyyy-MM-dd")
                        .field(DATE_FIELD))
                .get();

        System.out.println("testAggregationFormatIncorrect: " + searchResponse.getAggregations().get(AGGREGATION_NAME));
    }

    @Test
    public void testAggregationFormatCorrect() throws IOException {
        //setup indexes
        final String indexNameWithDateField = "a";
        final String indexNameWithoutDateField = "b";

        setup(indexNameWithDateField, indexNameWithoutDateField);

        final SearchResponse searchResponse = transportClient.prepareSearch("*")
                .addAggregation(AggregationBuilders.dateHistogram(AGGREGATION_NAME)
                        .dateHistogramInterval(DateHistogramInterval.MONTH)
                        .format("yyyy-MM-dd")
                        .field(DATE_FIELD))
                .get();

        System.out.println("testAggregationFormatCorrect: " + searchResponse.getAggregations().get(AGGREGATION_NAME));
    }

    private void setup(String indexNameWithDateField, String indexNameWithoutDateField) throws IOException {
        transportClient.admin().indices().prepareCreate(indexNameWithDateField)
                .addMapping(INDEX_TYPE, readMappingWithDateField(), XContentType.JSON)
                .get();

        transportClient.admin().indices().prepareCreate(indexNameWithoutDateField)
                .addMapping(INDEX_TYPE, readMappingWithoutDateField(), XContentType.JSON)
                .get();

        //create data
        transportClient.prepareIndex(indexNameWithDateField, INDEX_TYPE, "1")
                .setSource("{\"title\": \"1\", \"dateField\": \"2018-01-01\"}", XContentType.JSON)
                .get();

        transportClient.prepareIndex(indexNameWithoutDateField, INDEX_TYPE, "1")
                .setSource("{\"title\": \"1\"}", XContentType.JSON)
                .get();

        transportClient.admin().indices().prepareRefresh(indexNameWithDateField)
                .get();

        transportClient.admin().indices().prepareRefresh(indexNameWithoutDateField)
                .get();
    }

    private String readMappingWithDateField() throws IOException {
        return IOUtils.toString(this.getClass().getResourceAsStream("/searchIndexWithDateField.json"), "UTF-8");
    }

    private String readMappingWithoutDateField() throws IOException {
        return IOUtils.toString(this.getClass().getResourceAsStream("/searchIndexWithoutDateField.json"), "UTF-8");
    }

}

The output of these tests are:

testAggregationFormatIncorrect: {"dateTest":{"buckets":[{"key_as_string":"2018-01-01T00:00:00.000Z","key":1514764800000,"doc_count":1}]}}
testDateFieldFormatIncorrect: {"dateTest":{"buckets":[{"key_as_string":"2018-01-01T00:00:00.000Z","key":1514764800000,"doc_count":1}]}}
testDateFieldFormatCorrect: {"dateTest":{"buckets":[{"key_as_string":"2018-01-01","key":1514764800000,"doc_count":1}]}}
testAggregationFormatCorrect: {"dateTest":{"buckets":[{"key_as_string":"2018-01-01","key":1514764800000,"doc_count":1}]}}

You can see that the output for testAggregationFormatIncorrect and testDateFieldFormatIncorrect uses the default date format while the only difference is that the names of the indexes are switched.
I would expect that the output would be the same for all test cases.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions