Разные результаты "одинаковых" запросов

Два одинаковых запроса но во втором группировка по дате с шагом месяц, между датами 1ч 40 мин
Первый:

[
        'index' => 'index',
        'type' => 'type',
        'size' => 0,
        'body' => [
            'query' => [
                'filtered' => [
                    'query' => [ 'match_all' => [], ],
                    'filter' => [
                        'bool' => [
                            'must' => [
                                [ 'range' => [ 'event_at' => [ 'gte' => 1446394000, 'lte' => 1446399900, 'format' => 'epoch_second', ], ], ],
                                [ 'term' => [ 'project_id' => 2, ], ],
                                [ 'term' => [ 'country_id' => '2', ],],
                                [ 'term' => [ 'event_id' => 4, ], ],
                            ],
                        ],
                    ],
                  ],
              ],
            'aggregations' => [ 'dau' => [ 'cardinality' => [ 'field' => 'user_id', ], ], ],
          ],
      ]

Ответ:

  'hits' =>
  array (
    'total' => 623,
    'max_score' => 0,
    'hits' =>
    array (
    ),
  ),
  'aggregations' =>
  array (
    'dau' =>
    array (
      'value' => 99,
    ),
  ),

Второй запрос:

[
        'index' => 'index',
        'type' => 'type',
        'size' => 0,
        'body' =>
          [
            'query' => [
                'filtered' => [
                    'query' => ['match_all' => [], ],
                    'filter' => [
                        'bool' => [
                            'must' => [
                                  [ 'range' => [ 'event_at' => [ 'gte' => 1446394000, 'lte' => 1446399900, 'format' => 'epoch_second', ], ], ],
                                  [ 'term' => [ 'project_id' => 2, ], ],
                                  [ 'term' => [ 'country_id' => '2', ], ],
                                  [ 'term' => [ 'event_id' => 4, ], ],
                              ],
                          ],
                      ],
                  ],
              ],
            'aggregations' => [
                'date_range' => [
                    'date_histogram' => [ 'field' => 'event_at', 'interval' => 'month' ],
                    'aggregations' => [ 'dau' => [ 'cardinality' => [ 'field' => 'user_id' ] ] ]
                ]
            ]
          ]
      ]

Ответ:

'hits' =>
  array (
    'total' => 623,
    'max_score' => 0,
    'hits' =>
    array (
    ),
  ),
  'aggregations' =>
  array (
    'date_range' =>
    array (
      'buckets' =>
      array (
        0 =>
        array (
          'key_as_string' => '2015-11-01T00:00:00.000Z',
          'key' => 1446336000000,
          'doc_count' => 623,
          'dau' =>
          array (
            'value' => 98,
          ),
        ),
      ),
    ),
  ),

Разница в 1.
На большем диапазоне разрыв будет больше, хотя диапазон попадает в месяц и кол-во документов одинаковое.
С чем это может быть связано?

cardinality aggregation вычисляет количество документов приближенно. Вполне возможно, что в зависимости от того, как оно рассчитывается, вы получаете разные значения.

А есть возможность повлиять на точность?
Нашел ответ 'precision_threshold' => 100

Есть ли другой вариант точного расчета?

Если вам нужна абсолютная точность - то надо либо использовать агрегацию filter (но вам при это нужно знать все значения полей которые вас интересуют), либо использовать агрегацию terms со большим значением в shard_size. Этот параметр должен быть больше чем максимальное количество различных токенов в поле в одной шарде. То есть, если вы ищете по user_id, то shard_size должен быть равен ожидаемому количеству разных пользователей в одной шарде. Однако, все эти значения будут храниться в памяти и пересылаться между нодами во время запроса, так что данное решение плохо масштабируется.