Merge pull request #118 from apache/UNOMI-225-es7-fix-counts
UNOMI-225 ElasticSearch 7 fix for changes in the total hits
diff --git a/api/src/main/java/org/apache/unomi/api/PartialList.java b/api/src/main/java/org/apache/unomi/api/PartialList.java
index a78eb73..2128f93 100644
--- a/api/src/main/java/org/apache/unomi/api/PartialList.java
+++ b/api/src/main/java/org/apache/unomi/api/PartialList.java
@@ -35,10 +35,21 @@
private long offset;
private long pageSize;
private long totalSize;
+ private Relation totalSizeRelation;
private String scrollIdentifier = null;
private String scrollTimeValidity = null;
/**
+ * This enum exists to replicate Lucene's total hits relation in a back-end agnostic way. Basically Lucene will
+ * by default not report accurate total hit counts above a certain threshold for performance reasons. Using the
+ * relation we can understand if we are in the case of an accurate hit or not.
+ */
+ public enum Relation {
+ EQUAL,
+ GREATER_THAN_OR_EQUAL_TO
+ }
+
+ /**
* Instantiates a new PartialList.
*/
public PartialList() {
@@ -46,6 +57,7 @@
offset = 0;
pageSize = 0;
totalSize = 0;
+ totalSizeRelation = Relation.EQUAL;
}
/**
@@ -56,11 +68,12 @@
* @param pageSize the number of elements this PartialList contains
* @param totalSize the total size of elements in the original List
*/
- public PartialList(List<T> list, long offset, long pageSize, long totalSize) {
+ public PartialList(List<T> list, long offset, long pageSize, long totalSize, Relation totalSizeRelation) {
this.list = list;
this.offset = offset;
this.pageSize = pageSize;
this.totalSize = totalSize;
+ this.totalSizeRelation = totalSizeRelation;
}
/**
@@ -164,4 +177,17 @@
public void setScrollTimeValidity(String scrollTimeValidity) {
this.scrollTimeValidity = scrollTimeValidity;
}
+
+ /**
+ * Retrieve the relation to the total site, wether it is equal to or greater than the value stored in the
+ * totalSize property.
+ * @return a Relation enum value that describes the type of total size we have in this object.
+ */
+ public Relation getTotalSizeRelation() {
+ return totalSizeRelation;
+ }
+
+ public void setTotalSizeRelation(Relation totalSizeRelation) {
+ this.totalSizeRelation = totalSizeRelation;
+ }
}
diff --git a/extensions/lists-extension/services/src/main/java/org/apache/unomi/services/UserListServiceImpl.java b/extensions/lists-extension/services/src/main/java/org/apache/unomi/services/UserListServiceImpl.java
index e60cb19..237a52a 100644
--- a/extensions/lists-extension/services/src/main/java/org/apache/unomi/services/UserListServiceImpl.java
+++ b/extensions/lists-extension/services/src/main/java/org/apache/unomi/services/UserListServiceImpl.java
@@ -51,7 +51,7 @@
for (UserList definition : userLists.getList()) {
metadata.add(definition.getMetadata());
}
- return new PartialList<>(metadata, userLists.getOffset(), userLists.getPageSize(), userLists.getTotalSize());
+ return new PartialList<>(metadata, userLists.getOffset(), userLists.getPageSize(), userLists.getTotalSize(), userLists.getTotalSizeRelation());
}
public PartialList<Metadata> getListMetadatas(Query query) {
@@ -64,7 +64,7 @@
for (UserList definition : userLists.getList()) {
metadata.add(definition.getMetadata());
}
- return new PartialList<>(metadata, userLists.getOffset(), userLists.getPageSize(), userLists.getTotalSize());
+ return new PartialList<>(metadata, userLists.getOffset(), userLists.getPageSize(), userLists.getTotalSize(), userLists.getTotalSizeRelation());
}
@Override
diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
index 3d36784..812c184 100644
--- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
+++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
@@ -25,7 +25,7 @@
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+import org.apache.lucene.search.TotalHits;
import org.apache.unomi.api.Item;
import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.TimestampedItem;
@@ -55,6 +55,8 @@
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.*;
+import org.elasticsearch.client.core.CountRequest;
+import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.client.core.MainResponse;
import org.elasticsearch.client.indices.*;
import org.elasticsearch.cluster.metadata.MappingMetaData;
@@ -1346,13 +1348,13 @@
@Override
protected Long execute(Object... args) throws IOException {
- SearchRequest searchRequest = new SearchRequest(getIndexNameForQuery(itemType));
+
+ CountRequest countRequest = new CountRequest(getIndexNameForQuery(itemType));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(filter);
- searchSourceBuilder.size(0);
- searchRequest.source(searchSourceBuilder);
- SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
- return response.getHits().getTotalHits().value;
+ countRequest.source(searchSourceBuilder);
+ CountResponse response = client.count(countRequest, RequestOptions.DEFAULT);
+ return response.getCount();
}
}.catchingExecuteInClassLoader(true);
}
@@ -1365,6 +1367,7 @@
List<T> results = new ArrayList<T>();
String scrollIdentifier = null;
long totalHits = 0;
+ PartialList.Relation totalHitsRelation = PartialList.Relation.EQUAL;
try {
String itemType = Item.getItemType(clazz);
TimeValue keepAlive = TimeValue.timeValueHours(1);
@@ -1448,6 +1451,7 @@
SearchHits searchHits = response.getHits();
scrollIdentifier = response.getScrollId();
totalHits = searchHits.getTotalHits().value;
+ totalHitsRelation = getTotalHitsRelation(searchHits.getTotalHits());
for (SearchHit searchHit : searchHits) {
String sourceAsString = searchHit.getSourceAsString();
final T value = ESCustomObjectMapper.getObjectMapper().readValue(sourceAsString, clazz);
@@ -1460,7 +1464,7 @@
throw new Exception("Error loading itemType=" + clazz.getName() + " query=" + query + " sortBy=" + sortBy, t);
}
- PartialList<T> result = new PartialList<T>(results, offset, size, totalHits);
+ PartialList<T> result = new PartialList<T>(results, offset, size, totalHits, totalHitsRelation);
if (scrollIdentifier != null && totalHits != 0) {
result.setScrollIdentifier(scrollIdentifier);
result.setScrollTimeValidity(scrollTimeValidity);
@@ -1470,6 +1474,10 @@
}.catchingExecuteInClassLoader(true);
}
+ private PartialList.Relation getTotalHitsRelation(TotalHits totalHits) {
+ return TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO.equals(totalHits.relation) ? PartialList.Relation.GREATER_THAN_OR_EQUAL_TO : PartialList.Relation.EQUAL;
+ }
+
@Override
public <T extends Item> PartialList<T> continueScrollQuery(final Class<T> clazz, final String scrollIdentifier, final String scrollTimeValidity) {
return new InClassLoaderExecute<PartialList<T>>(metricsService, this.getClass().getName() + ".continueScrollQuery") {
@@ -1499,7 +1507,7 @@
results.add(value);
}
}
- PartialList<T> result = new PartialList<T>(results, 0, response.getHits().getHits().length, response.getHits().getTotalHits().value);
+ PartialList<T> result = new PartialList<T>(results, 0, response.getHits().getHits().length, response.getHits().getTotalHits().value, getTotalHitsRelation(response.getHits().getTotalHits()));
if (scrollIdentifier != null) {
result.setScrollIdentifier(scrollIdentifier);
result.setScrollTimeValidity(scrollTimeValidity);
@@ -1657,13 +1665,19 @@
}
}
if (aggregations.get("buckets") != null) {
+ long totalDocCount = 0;
MultiBucketsAggregation terms = aggregations.get("buckets");
for (MultiBucketsAggregation.Bucket bucket : terms.getBuckets()) {
results.put(bucket.getKeyAsString(), bucket.getDocCount());
+ totalDocCount += bucket.getDocCount();
}
SingleBucketAggregation missing = aggregations.get("missing");
if (missing.getDocCount() > 0) {
results.put("_missing", missing.getDocCount());
+ totalDocCount += missing.getDocCount();
+ }
+ if (response.getHits() != null && TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO.equals(response.getHits().getTotalHits().relation)) {
+ results.put("_filtered", totalDocCount);
}
}
}
diff --git a/services/src/main/java/org/apache/unomi/services/impl/AbstractServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/AbstractServiceImpl.java
index 22cf911..1368105 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/AbstractServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/AbstractServiceImpl.java
@@ -50,7 +50,7 @@
for (T definition : items.getList()) {
details.add(definition.getMetadata());
}
- return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize());
+ return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize(), items.getTotalSizeRelation());
}
protected <T extends MetadataItem> PartialList<Metadata> getMetadatas(Query query, Class<T> clazz) {
@@ -63,6 +63,6 @@
for (T definition : items.getList()) {
details.add(definition.getMetadata());
}
- return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize());
+ return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize(), items.getTotalSizeRelation());
}
}
diff --git a/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java
index 336eac9..cf2788e 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java
@@ -360,7 +360,7 @@
details.add(campaignDetail);
}
}
- return new PartialList<>(details, campaigns.getOffset(), campaigns.getPageSize(), campaigns.getTotalSize());
+ return new PartialList<>(details, campaigns.getOffset(), campaigns.getPageSize(), campaigns.getTotalSize(), campaigns.getTotalSizeRelation());
}
public CampaignDetail getCampaignDetail(String id) {
diff --git a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
index 6506b42..4f7161a 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
@@ -314,7 +314,7 @@
for (Rule definition : rules.getList()) {
descriptions.add(definition.getMetadata());
}
- return new PartialList<>(descriptions, rules.getOffset(), rules.getPageSize(), rules.getTotalSize());
+ return new PartialList<>(descriptions, rules.getOffset(), rules.getPageSize(), rules.getTotalSize(), rules.getTotalSizeRelation());
}
public PartialList<Rule> getRuleDetails(Query query) {
@@ -325,7 +325,7 @@
PartialList<Rule> rules = persistenceService.query(query.getCondition(), query.getSortby(), Rule.class, query.getOffset(), query.getLimit());
List<Rule> details = new LinkedList<>();
details.addAll(rules.getList());
- return new PartialList<>(details, rules.getOffset(), rules.getPageSize(), rules.getTotalSize());
+ return new PartialList<>(details, rules.getOffset(), rules.getPageSize(), rules.getTotalSize(), rules.getTotalSizeRelation());
}
public Rule getRule(String ruleId) {
diff --git a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
index 047751c..212c1b1 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
@@ -198,7 +198,7 @@
for (Segment definition : segments.getList()) {
details.add(definition.getMetadata());
}
- return new PartialList<>(details, segments.getOffset(), segments.getPageSize(), segments.getTotalSize());
+ return new PartialList<>(details, segments.getOffset(), segments.getPageSize(), segments.getTotalSize(), segments.getTotalSizeRelation());
}
public PartialList<Metadata> getSegmentMetadatas(Query query) {