Merge "Update testcontainers to 1.17.5" into stable-3.5
diff --git a/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index 3b300cf..908d9a7 100644
--- a/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -43,6 +43,7 @@
 import com.google.gerrit.index.Schema;
 import com.google.gerrit.index.query.DataSource;
 import com.google.gerrit.index.query.FieldBundle;
+import com.google.gerrit.index.query.HasCardinality;
 import com.google.gerrit.index.query.ListResultSet;
 import com.google.gerrit.index.query.Predicate;
 import com.google.gerrit.index.query.QueryParseException;
@@ -362,26 +363,32 @@
 
   protected class ElasticQuerySource implements DataSource<V> {
     private final QueryOptions opts;
+    private final Predicate<V> predicate;
     private final String search;
 
     ElasticQuerySource(Predicate<V> p, QueryOptions opts, JsonArray sortArray)
         throws QueryParseException {
       this.opts = opts;
+      this.predicate = p;
       QueryBuilder qb = queryBuilder.toQueryBuilder(p);
       SearchSourceBuilder searchSource =
           new SearchSourceBuilder(client.adapter())
               .query(qb)
               .size(opts.pageSize())
-              .fields(Lists.newArrayList(opts.fields()));
+              .fields(Lists.newArrayList(opts.fields()))
+              .trackTotalHits(false);
       searchSource =
           opts.searchAfter() != null
-              ? searchSource.searchAfter((JsonArray) opts.searchAfter()).trackTotalHits(false)
+              ? searchSource.searchAfter((JsonArray) opts.searchAfter())
               : searchSource.from(opts.start());
       search = getSearch(searchSource, sortArray);
     }
 
     @Override
     public int getCardinality() {
+      if (predicate instanceof HasCardinality) {
+        return ((HasCardinality) predicate).getCardinality();
+      }
       return 10;
     }
 
diff --git a/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java b/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java
index edd05c9..6bae325 100644
--- a/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java
+++ b/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java
@@ -23,7 +23,7 @@
 class ElasticMapping {
 
   protected static final String TIMESTAMP_FIELD_TYPE = "date";
-  protected static final String TIMESTAMP_FIELD_FORMAT = "dateOptionalTime";
+  protected static final String TIMESTAMP_FIELD_FORMAT = "date_optional_time";
 
   static MappingProperties createMapping(Schema<?> schema, ElasticQueryAdapter adapter) {
     ElasticMapping.Builder mapping = new ElasticMapping.Builder(adapter);
diff --git a/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java b/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
index 40ac603..cde5560 100644
--- a/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
+++ b/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
@@ -52,7 +52,7 @@
   private <T> BoolQueryBuilder and(Predicate<T> p) throws QueryParseException {
     BoolQueryBuilder b = QueryBuilders.boolQuery();
     for (Predicate<T> c : p.getChildren()) {
-      b.must(toQueryBuilder(c));
+      b.filter(toQueryBuilder(c));
     }
     return b;
   }
@@ -73,7 +73,7 @@
 
     // Lucene does not support negation, start with all and subtract.
     BoolQueryBuilder q = QueryBuilders.boolQuery();
-    q.must(QueryBuilders.matchAllQuery());
+    q.filter(QueryBuilders.matchAllQuery());
     q.mustNot(toQueryBuilder(n));
     return q;
   }
diff --git a/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java b/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
index a204919..741aec7 100644
--- a/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
+++ b/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
@@ -42,6 +42,15 @@
   }
 
   /**
+   * Adds a query that <b>must</b> appear in the matching documents and will not contribute to
+   * scoring.
+   */
+  public BoolQueryBuilder filter(QueryBuilder queryBuilder) {
+    filterClauses.add(queryBuilder);
+    return this;
+  }
+
+  /**
    * Adds a query that <b>must not</b> appear in the matching documents and will not contribute to
    * scoring.
    */