diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/eql/EqlSearchResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/eql/EqlSearchResponseTests.java index f25da7d4f9169..2cc82656f20cd 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/eql/EqlSearchResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/eql/EqlSearchResponseTests.java @@ -43,7 +43,7 @@ static List randomEvents() { if (randomBoolean()) { hits = new ArrayList<>(); for (int i = 0; i < size; i++) { - hits.add(new SearchHit(i, randomAlphaOfLength(10), null, new HashMap<>())); + hits.add(new SearchHit(i, randomAlphaOfLength(10), null, new HashMap<>(), new HashMap<>())); } } if (randomBoolean()) { diff --git a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateResponseTests.java b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateResponseTests.java index c02c311550185..e1244c7aa37c3 100644 --- a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateResponseTests.java +++ b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateResponseTests.java @@ -165,7 +165,7 @@ public void testSourceToXContent() throws IOException { } public void testSearchResponseToXContent() throws IOException { - SearchHit hit = new SearchHit(1, "id", new Text("type"), Collections.emptyMap()); + SearchHit hit = new SearchHit(1, "id", new Text("type"), Collections.emptyMap(), Collections.emptyMap()); hit.score(2.0f); SearchHit[] hits = new SearchHit[] { hit }; diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java index c85018b99e996..7c3d867db4365 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java @@ -102,7 +102,7 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept shardContext.lookup().source().setSegmentAndDocument(percolatorLeafReaderContext, slot); shardContext.lookup().source().setSource(document); hitContext.reset( - new SearchHit(slot, "unknown", new Text(hit.getType()), Collections.emptyMap()), + new SearchHit(slot, "unknown", new Text(hit.getType()), Collections.emptyMap(), Collections.emptyMap()), percolatorLeafReaderContext, slot, percolatorIndexSearcher ); hitContext.cache().clear(); diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorMatchedSlotSubFetchPhase.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorMatchedSlotSubFetchPhase.java index fdcc9156b415e..bebaf856d1f98 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorMatchedSlotSubFetchPhase.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorMatchedSlotSubFetchPhase.java @@ -110,7 +110,7 @@ static void innerHitsExecute(Query mainQuery, IndexSearcher indexSearcher, Searc hit.fields(fields); } IntStream slots = convertTopDocsToSlots(topDocs, rootDocsBySlot); - fields.put(fieldName, new DocumentField(fieldName, slots.boxed().collect(Collectors.toList()))); + hit.setField(fieldName, new DocumentField(fieldName, slots.boxed().collect(Collectors.toList()))); } } } diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/DiscountedCumulativeGainTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/DiscountedCumulativeGainTests.java index 30c4f037b2a59..a8efea05b01d2 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/DiscountedCumulativeGainTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/DiscountedCumulativeGainTests.java @@ -74,7 +74,8 @@ public void testDCGAt() { SearchHit[] hits = new SearchHit[6]; for (int i = 0; i < 6; i++) { rated.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i])); - hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } DiscountedCumulativeGain dcg = new DiscountedCumulativeGain(); @@ -124,7 +125,8 @@ public void testDCGAtSixMissingRatings() { rated.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i])); } } - hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } DiscountedCumulativeGain dcg = new DiscountedCumulativeGain(); @@ -181,7 +183,8 @@ public void testDCGAtFourMoreRatings() { // only create four hits SearchHit[] hits = new SearchHit[4]; for (int i = 0; i < 4; i++) { - hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } DiscountedCumulativeGain dcg = new DiscountedCumulativeGain(); diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/ExpectedReciprocalRankTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/ExpectedReciprocalRankTests.java index 7a3b9e3061a26..8fcbb2a2f2fbb 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/ExpectedReciprocalRankTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/ExpectedReciprocalRankTests.java @@ -117,7 +117,8 @@ private SearchHit[] createSearchHits(List rated, Integer[] releva if (relevanceRatings[i] != null) { rated.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i])); } - hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + hits[i] = new SearchHit(i, Integer.toString(i), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } return hits; diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/MeanReciprocalRankTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/MeanReciprocalRankTests.java index 6b37fee3c5e8a..51112ede57d32 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/MeanReciprocalRankTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/MeanReciprocalRankTests.java @@ -204,7 +204,7 @@ public void testXContentParsingIsNotLenient() throws IOException { private static SearchHit[] createSearchHits(int from, int to, String index) { SearchHit[] hits = new SearchHit[to + 1 - from]; for (int i = from; i <= to; i++) { - hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap()); + hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId(index, "uuid", 0), null, OriginalIndices.NONE)); } return hits; diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/PrecisionAtKTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/PrecisionAtKTests.java index cbc60c231cbde..a00f5047d0e86 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/PrecisionAtKTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/PrecisionAtKTests.java @@ -114,7 +114,7 @@ public void testIgnoreUnlabeled() { rated.add(createRatedDoc("test", "1", RELEVANT_RATING)); // add an unlabeled search hit SearchHit[] searchHits = Arrays.copyOf(toSearchHits(rated, "test"), 3); - searchHits[2] = new SearchHit(2, "2", new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + searchHits[2] = new SearchHit(2, "2", new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap(), Collections.emptyMap()); searchHits[2].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); EvalQueryQuality evaluated = (new PrecisionAtK()).evaluate("id", searchHits, rated); @@ -133,7 +133,8 @@ public void testIgnoreUnlabeled() { public void testNoRatedDocs() throws Exception { SearchHit[] hits = new SearchHit[5]; for (int i = 0; i < 5; i++) { - hits[i] = new SearchHit(i, i + "", new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + hits[i] = new SearchHit(i, i + "", new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } EvalQueryQuality evaluated = (new PrecisionAtK()).evaluate("id", hits, Collections.emptyList()); @@ -255,7 +256,7 @@ private static PrecisionAtK mutate(PrecisionAtK original) { private static SearchHit[] toSearchHits(List rated, String index) { SearchHit[] hits = new SearchHit[rated.size()]; for (int i = 0; i < rated.size(); i++) { - hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap()); + hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId(index, "uuid", 0), null, OriginalIndices.NONE)); } return hits; diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RankEvalResponseTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RankEvalResponseTests.java index 1939b5e19c1a6..a723b4690b9c3 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RankEvalResponseTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RankEvalResponseTests.java @@ -181,7 +181,8 @@ public void testToXContent() throws IOException { } private static RatedSearchHit searchHit(String index, int docId, Integer rating) { - SearchHit hit = new SearchHit(docId, docId + "", new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + SearchHit hit = new SearchHit(docId, docId + "", new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap()); hit.shard(new SearchShardTarget("testnode", new ShardId(index, "uuid", 0), null, OriginalIndices.NONE)); hit.score(1.0f); return new RatedSearchHit(hit, rating != null ? OptionalInt.of(rating) : OptionalInt.empty()); diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RatedSearchHitTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RatedSearchHitTests.java index 384503a28016f..7d8121c0ee540 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RatedSearchHitTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RatedSearchHitTests.java @@ -42,7 +42,7 @@ public static RatedSearchHit randomRatedSearchHit() { OptionalInt rating = randomBoolean() ? OptionalInt.empty() : OptionalInt.of(randomIntBetween(0, 5)); SearchHit searchHit = new SearchHit(randomIntBetween(0, 10), randomAlphaOfLength(10), - new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap(), Collections.emptyMap()); RatedSearchHit ratedSearchHit = new RatedSearchHit(searchHit, rating); return ratedSearchHit; } @@ -56,7 +56,7 @@ private static RatedSearchHit mutateTestItem(RatedSearchHit original) { break; case 1: hit = new SearchHit(hit.docId(), hit.getId() + randomAlphaOfLength(10), - new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap()); + new Text(MapperService.SINGLE_MAPPING_NAME), Collections.emptyMap(), Collections.emptyMap()); break; default: throw new IllegalStateException("The test should only allow two parameters mutated"); diff --git a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RecallAtKTests.java b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RecallAtKTests.java index f49d2ff9db796..5f2f27ffc8fd5 100644 --- a/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RecallAtKTests.java +++ b/modules/rank-eval/src/test/java/org/elasticsearch/index/rankeval/RecallAtKTests.java @@ -115,7 +115,7 @@ public void testNoRatedDocs() throws Exception { int k = 5; SearchHit[] hits = new SearchHit[k]; for (int i = 0; i < k; i++) { - hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap()); + hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0), null, OriginalIndices.NONE)); } @@ -237,7 +237,7 @@ private static RecallAtK mutate(RecallAtK original) { private static SearchHit[] toSearchHits(List rated, String index) { SearchHit[] hits = new SearchHit[rated.size()]; for (int i = 0; i < rated.size(); i++) { - hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap()); + hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap(), Collections.emptyMap()); hits[i].shard(new SearchShardTarget("testnode", new ShardId(index, "uuid", 0), null, OriginalIndices.NONE)); } return hits; diff --git a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/AsyncBulkByScrollActionTests.java b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/AsyncBulkByScrollActionTests.java index ae451364a289a..d4ea484cadd94 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/AsyncBulkByScrollActionTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/AsyncBulkByScrollActionTests.java @@ -504,7 +504,7 @@ protected RequestWrapper buildRequest(Hit doc) { action.start(); // create a simulated response. - SearchHit hit = new SearchHit(0, "id", new Text("type"), emptyMap()).sourceRef(new BytesArray("{}")); + SearchHit hit = new SearchHit(0, "id", new Text("type"), emptyMap(), emptyMap()).sourceRef(new BytesArray("{}")); SearchHits hits = new SearchHits(IntStream.range(0, 100).mapToObj(i -> hit).toArray(SearchHit[]::new), new TotalHits(0, TotalHits.Relation.EQUAL_TO),0); InternalSearchResponse internalResponse = new InternalSearchResponse(hits, null, null, null, false, false, 1); diff --git a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ClientScrollableHitSourceTests.java b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ClientScrollableHitSourceTests.java index 6526f608109b3..29b4b81069998 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ClientScrollableHitSourceTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ClientScrollableHitSourceTests.java @@ -160,7 +160,7 @@ public void testScrollKeepAlive() { private SearchResponse createSearchResponse() { // create a simulated response. - SearchHit hit = new SearchHit(0, "id", new Text("type"), emptyMap()).sourceRef(new BytesArray("{}")); + SearchHit hit = new SearchHit(0, "id", new Text("type"), emptyMap(), emptyMap()).sourceRef(new BytesArray("{}")); SearchHits hits = new SearchHits(IntStream.range(0, randomIntBetween(0, 20)).mapToObj(i -> hit).toArray(SearchHit[]::new), new TotalHits(0, TotalHits.Relation.EQUAL_TO),0); InternalSearchResponse internalResponse = new InternalSearchResponse(hits, null, null, null, false, false, 1); diff --git a/server/src/main/java/org/elasticsearch/search/SearchHit.java b/server/src/main/java/org/elasticsearch/search/SearchHit.java index 8da9df7a50468..6063d192ace8a 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchHit.java +++ b/server/src/main/java/org/elasticsearch/search/SearchHit.java @@ -96,7 +96,8 @@ public final class SearchHit implements Writeable, ToXContentObject, Iterable fields; + private Map documentFields; + private Map metaFields; private Map highlightFields = null; @@ -121,14 +122,15 @@ public final class SearchHit implements Writeable, ToXContentObject, Iterable fields) { - this(docId, id, type, null, fields); + public SearchHit(int docId, String id, Text type, Map documentFields, Map metaFields) { + this(docId, id, type, null, documentFields, metaFields); } - public SearchHit(int nestedTopDocId, String id, Text type, NestedIdentity nestedIdentity, Map fields) { + public SearchHit(int nestedTopDocId, String id, Text type, NestedIdentity nestedIdentity, + Map documentFields, Map metaFields) { this.docId = nestedTopDocId; if (id != null) { this.id = new Text(id); @@ -137,7 +139,15 @@ public SearchHit(int nestedTopDocId, String id, Text type, NestedIdentity nested } this.type = type; this.nestedIdentity = nestedIdentity; - this.fields = fields; + this.documentFields = documentFields; + if (this.documentFields == null) { + this.documentFields = new HashMap<>(); + } + + this.metaFields = metaFields; + if (this.metaFields == null) { + this.metaFields = new HashMap<>(); + } } public SearchHit(StreamInput in) throws IOException { @@ -158,22 +168,17 @@ public SearchHit(StreamInput in) throws IOException { if (in.readBoolean()) { explanation = readExplanation(in); } - int size = in.readVInt(); - if (size == 0) { - fields = emptyMap(); - } else if (size == 1) { - DocumentField hitField = new DocumentField(in); - fields = singletonMap(hitField.getName(), hitField); + if (in.getVersion().onOrAfter(Version.V_7_8_0)) { + documentFields = in.readMap(StreamInput::readString, DocumentField::new); + metaFields = in.readMap(StreamInput::readString, DocumentField::new); } else { - Map fields = new HashMap<>(); - for (int i = 0; i < size; i++) { - DocumentField hitField = new DocumentField(in); - fields.put(hitField.getName(), hitField); - } - this.fields = unmodifiableMap(fields); + Map fields = readFields(in); + documentFields = new HashMap<>(); + metaFields = new HashMap<>(); + SearchHit.splitFieldsByMetadata(fields, documentFields, metaFields); } - size = in.readVInt(); + int size = in.readVInt(); if (size == 0) { highlightFields = emptyMap(); } else if (size == 1) { @@ -212,6 +217,36 @@ public SearchHit(StreamInput in) throws IOException { } } + private Map readFields(StreamInput in) throws IOException { + Map fields; + int size = in.readVInt(); + if (size == 0) { + fields = emptyMap(); + } else if (size == 1) { + DocumentField hitField = new DocumentField(in); + fields = singletonMap(hitField.getName(), hitField); + } else { + fields = new HashMap<>(size); + for (int i = 0; i < size; i++) { + DocumentField field = new DocumentField(in); + fields.put(field.getName(), field); + } + fields = unmodifiableMap(fields); + } + return fields; + } + + private void writeFields(StreamOutput out, Map fields) throws IOException { + if (fields == null) { + out.writeVInt(0); + } else { + out.writeVInt(fields.size()); + for (DocumentField field : fields.values()) { + field.writeTo(out); + } + } + } + @Override public void writeTo(StreamOutput out) throws IOException { out.writeFloat(score); @@ -230,13 +265,11 @@ public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(true); writeExplanation(out, explanation); } - if (fields == null) { - out.writeVInt(0); + if (out.getVersion().onOrAfter(Version.V_7_8_0)) { + out.writeMap(documentFields, StreamOutput::writeString, (stream, documentField) -> documentField.writeTo(stream)); + out.writeMap(metaFields, StreamOutput::writeString, (stream, documentField) -> documentField.writeTo(stream)); } else { - out.writeVInt(fields.size()); - for (DocumentField hitField : getFields().values()) { - hitField.writeTo(out); - } + writeFields(out, this.getFields()); } if (highlightFields == null) { out.writeVInt(0); @@ -415,7 +448,9 @@ public Map getSourceAsMap() { @Override public Iterator iterator() { - return fields.values().iterator(); + // need to join the fields and metadata fields + Map allFields = this.getFields(); + return allFields.values().iterator(); } /** @@ -425,21 +460,45 @@ public DocumentField field(String fieldName) { return getFields().get(fieldName); } + /* + * Adds a new DocumentField to the map in case both parameters are not null. + * */ + public void setField(String fieldName, DocumentField field) { + if (fieldName == null || field == null) return; + if (field.isMetadataField()) { + this.metaFields.put(fieldName, field); + } else { + this.documentFields.put(fieldName, field); + } + } + /** * A map of hit fields (from field name to hit fields) if additional fields * were required to be loaded. */ public Map getFields() { - return fields == null ? emptyMap() : fields; + Map fields = new HashMap<>(); + fields.putAll(metaFields); + fields.putAll(documentFields); + return fields; } // returns the fields without handling null cases public Map fieldsOrNull() { - return fields; + return getFields(); } public void fields(Map fields) { - this.fields = fields; + Objects.requireNonNull(fields); + this.metaFields = new HashMap<>(); + this.documentFields = new HashMap<>(); + for (Map.Entry fieldEntry: fields.entrySet()) { + if (fieldEntry.getValue().isMetadataField()) { + this.metaFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } else { + this.documentFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } + } } /** @@ -538,6 +597,22 @@ public void setInnerHits(Map innerHits) { this.innerHits = innerHits; } + public static void splitFieldsByMetadata(Map fields, + Map documentFields, + Map metaFields) { + // documentFields and metaFields must be non-empty maps + if (fields == null) { + return; + } + for (Map.Entry fieldEntry: fields.entrySet()) { + if (fieldEntry.getValue().isMetadataField()) { + metaFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } else { + documentFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } + } + } + public static class Fields { static final String _INDEX = "_index"; static final String _TYPE = "_type"; @@ -559,6 +634,12 @@ public static class Fields { static final String _NODE = "_node"; } + // Following are the keys for storing the metadata fields and regular fields in the aggregation map. + // These do not influence the structure of json serialization: document fields are still stored + // under FIELDS and metadata are still scattered at the root level. + static final String DOCUMENT_FIELDS = "document_fields"; + static final String METADATA_FIELDS = "metadata_fields"; + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); @@ -569,21 +650,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws // public because we render hit as part of completion suggestion option public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) throws IOException { - List metaFields = new ArrayList<>(); - List otherFields = new ArrayList<>(); - if (fields != null && !fields.isEmpty()) { - for (DocumentField field : fields.values()) { - if (field.getValues().isEmpty()) { - continue; - } - if (field.isMetadataField()) { - metaFields.add(field); - } else { - otherFields.add(field); - } - } - } - // For inner_hit hits shard is null and that is ok, because the parent search hit has all this information. // Even if this was included in the inner_hit hits this would be the same, so better leave it out. if (getExplanation() != null && shard != null) { @@ -616,7 +682,7 @@ public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) t } else { builder.field(Fields._SCORE, score); } - for (DocumentField field : metaFields) { + for (DocumentField field : metaFields.values()) { // _ignored is the only multi-valued meta field // TODO: can we avoid having an exception here? if (field.getName().equals(IgnoredFieldMapper.NAME)) { @@ -628,9 +694,9 @@ public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) t if (source != null) { XContentHelper.writeRawField(SourceFieldMapper.NAME, source, builder, params); } - if (!otherFields.isEmpty()) { + if (!documentFields.isEmpty()) { builder.startObject(Fields.FIELDS); - for (DocumentField field : otherFields) { + for (DocumentField field : documentFields.values()) { field.toXContent(builder, params); } builder.endObject(); @@ -706,7 +772,7 @@ public static void declareInnerHitsParseFields(ObjectParser, parser.declareObject((map, value) -> { Map fieldMap = get(Fields.FIELDS, map, new HashMap()); fieldMap.putAll(value); - map.put(Fields.FIELDS, fieldMap); + map.put(DOCUMENT_FIELDS, fieldMap); }, (p, c) -> parseFields(p), new ParseField(Fields.FIELDS)); parser.declareObject((map, value) -> map.put(Fields._EXPLANATION, value), (p, c) -> parseExplanation(p), new ParseField(Fields._EXPLANATION)); @@ -723,9 +789,10 @@ public static SearchHit createFromMap(Map values) { String id = get(Fields._ID, values, null); Text type = get(Fields._TYPE, values, null); NestedIdentity nestedIdentity = get(NestedIdentity._NESTED, values, null); - Map fields = get(Fields.FIELDS, values, Collections.emptyMap()); + Map metaFields = get(METADATA_FIELDS, values, Collections.emptyMap()); + Map documentFields = get(DOCUMENT_FIELDS, values, Collections.emptyMap()); - SearchHit searchHit = new SearchHit(-1, id, type, nestedIdentity, fields); + SearchHit searchHit = new SearchHit(-1, id, type, nestedIdentity, documentFields, metaFields); String index = get(Fields._INDEX, values, null); String clusterAlias = null; if (index != null) { @@ -790,13 +857,17 @@ private static BytesReference parseSourceBytes(XContentParser parser) throws IOE * handled individually. All other fields are parsed to an entry in the fields map */ private static void declareMetadataFields(ObjectParser, Void> parser) { + /* TODO: This method and its usage in declareInnerHitsParseFields() must be replaced by + calling an UnknownFieldConsumer. All fields on the root level of the parsed SearhHit + should be interpreted as metadata fields. + */ for (String metadatafield : MapperService.getAllMetaFields()) { if (metadatafield.equals(Fields._ID) == false && metadatafield.equals(Fields._INDEX) == false && metadatafield.equals(Fields._TYPE) == false) { if (metadatafield.equals(IgnoredFieldMapper.NAME)) { parser.declareObjectArray((map, list) -> { @SuppressWarnings("unchecked") - Map fieldMap = (Map) map.computeIfAbsent(Fields.FIELDS, + Map fieldMap = (Map) map.computeIfAbsent(METADATA_FIELDS, v -> new HashMap()); DocumentField field = new DocumentField(metadatafield, list); fieldMap.put(field.getName(), field); @@ -805,7 +876,7 @@ private static void declareMetadataFields(ObjectParser, Void } else { parser.declareField((map, field) -> { @SuppressWarnings("unchecked") - Map fieldMap = (Map) map.computeIfAbsent(Fields.FIELDS, + Map fieldMap = (Map) map.computeIfAbsent(METADATA_FIELDS, v -> new HashMap()); fieldMap.put(field.getName(), field); }, (p, c) -> new DocumentField(metadatafield, Collections.singletonList(parseFieldsValue(p))), @@ -906,7 +977,8 @@ public boolean equals(Object obj) { && Objects.equals(seqNo, other.seqNo) && Objects.equals(primaryTerm, other.primaryTerm) && Objects.equals(source, other.source) - && Objects.equals(getFields(), other.getFields()) + && Objects.equals(documentFields, other.documentFields) + && Objects.equals(metaFields, other.metaFields) && Objects.equals(getHighlightFields(), other.getHighlightFields()) && Arrays.equals(matchedQueries, other.matchedQueries) && Objects.equals(explanation, other.explanation) @@ -918,7 +990,7 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return Objects.hash(id, type, nestedIdentity, version, seqNo, primaryTerm, source, fields, getHighlightFields(), + return Objects.hash(id, nestedIdentity, version, seqNo, primaryTerm, source, documentFields, metaFields, getHighlightFields(), Arrays.hashCode(matchedQueries), explanation, shard, innerHits, index, clusterAlias); } diff --git a/server/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java b/server/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java index 93501678e43ed..a4a32b3a7c513 100644 --- a/server/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java +++ b/server/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java @@ -209,13 +209,17 @@ private SearchHit createSearchHit(SearchContext context, DocumentMapper documentMapper = context.mapperService().documentMapper(); Text typeText = documentMapper.typeText(); if (fieldsVisitor == null) { - return new SearchHit(docId, null, typeText, null); + return new SearchHit(docId, null, typeText, null, null); } Map searchFields = getSearchFields(context, fieldsVisitor, subDocId, storedToRequestedFields, subReaderContext); - SearchHit searchHit = new SearchHit(docId, fieldsVisitor.uid().id(), typeText, searchFields); + Map metaFields = new HashMap<>(); + Map documentFields = new HashMap<>(); + SearchHit.splitFieldsByMetadata(searchFields, documentFields, metaFields); + + SearchHit searchHit = new SearchHit(docId, fieldsVisitor.uid().id(), typeText, documentFields, metaFields); // Set _source if requested. SourceLookup sourceLookup = context.lookup().source(); sourceLookup.setSegmentAndDocument(subReaderContext, subDocId); @@ -341,7 +345,10 @@ private SearchHit createNestedSearchHit(SearchContext context, XContentType contentType = tuple.v1(); context.lookup().source().setSourceContentType(contentType); } - return new SearchHit(nestedTopDocId, uid.id(), documentMapper.typeText(), nestedIdentity, searchFields); + Map metaFields = new HashMap<>(); + Map documentFields = new HashMap<>(); + SearchHit.splitFieldsByMetadata(searchFields, documentFields, metaFields); + return new SearchHit(nestedTopDocId, uid.id(), documentMapper.typeText(), nestedIdentity, documentFields, metaFields); } private SearchHit.NestedIdentity getInternalNestedIdentity(SearchContext context, int nestedSubDocId, diff --git a/server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchDocValuesPhase.java b/server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchDocValuesPhase.java index d03e5cde7faf8..f0b26a468db93 100644 --- a/server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchDocValuesPhase.java +++ b/server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchDocValuesPhase.java @@ -148,7 +148,7 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept DocumentField hitField = hit.getFields().get(field); if (hitField == null) { hitField = new DocumentField(field, new ArrayList<>(2)); - hit.getFields().put(field, hitField); + hit.setField(field, hitField); } final List values = hitField.getValues(); diff --git a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsPhase.java b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsPhase.java index 7a015811bd1f0..affe1920f4817 100644 --- a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsPhase.java +++ b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsPhase.java @@ -85,7 +85,8 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept values = Collections.singletonList(value); } hitField = new DocumentField(scriptFieldName, values); - hit.getFields().put(scriptFieldName, hitField); + hit.setField(scriptFieldName, hitField); + } } } diff --git a/server/src/test/java/org/elasticsearch/action/search/ExpandSearchPhaseTests.java b/server/src/test/java/org/elasticsearch/action/search/ExpandSearchPhaseTests.java index 783bf7e10fe4c..e7254799f3b90 100644 --- a/server/src/test/java/org/elasticsearch/action/search/ExpandSearchPhaseTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/ExpandSearchPhaseTests.java @@ -52,8 +52,8 @@ public void testCollapseSingleHit() throws IOException { List collapsedHits = new ArrayList<>(numInnerHits); for (int innerHitNum = 0; innerHitNum < numInnerHits; innerHitNum++) { SearchHits hits = new SearchHits(new SearchHit[]{new SearchHit(innerHitNum, "ID", new Text("type"), - Collections.emptyMap()), new SearchHit(innerHitNum + 1, "ID", new Text("type"), - Collections.emptyMap())}, new TotalHits(2, TotalHits.Relation.EQUAL_TO), 1.0F); + Collections.emptyMap(), Collections.emptyMap()), new SearchHit(innerHitNum + 1, "ID", new Text("type"), + Collections.emptyMap(), Collections.emptyMap())}, new TotalHits(2, TotalHits.Relation.EQUAL_TO), 1.0F); collapsedHits.add(hits); } @@ -103,8 +103,8 @@ void sendExecuteMultiSearch(MultiSearchRequest request, SearchTask task, ActionL }; SearchHits hits = new SearchHits(new SearchHit[]{new SearchHit(1, "ID", new Text("type"), - Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(collapseValue))))}, - new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); + Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(collapseValue))), + Collections.emptyMap())}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); InternalSearchResponse internalSearchResponse = new InternalSearchResponse(hits, null, null, null, false, null, 1); ExpandSearchPhase phase = new ExpandSearchPhase(mockSearchPhaseContext, internalSearchResponse, null); @@ -126,8 +126,8 @@ public void testFailOneItemFailsEntirePhase() throws IOException { AtomicBoolean executedMultiSearch = new AtomicBoolean(false); SearchHits collapsedHits = new SearchHits(new SearchHit[]{new SearchHit(2, "ID", new Text("type"), - Collections.emptyMap()), new SearchHit(3, "ID", new Text("type"), - Collections.emptyMap())}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); + Collections.emptyMap(), Collections.emptyMap()), new SearchHit(3, "ID", new Text("type"), + Collections.emptyMap(), Collections.emptyMap())}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); MockSearchPhaseContext mockSearchPhaseContext = new MockSearchPhaseContext(1); String collapseValue = randomBoolean() ? null : "boom"; mockSearchPhaseContext.getRequest().source(new SearchSourceBuilder() @@ -149,9 +149,9 @@ void sendExecuteMultiSearch(MultiSearchRequest request, SearchTask task, ActionL }; SearchHits hits = new SearchHits(new SearchHit[]{new SearchHit(1, "ID", new Text("type"), - Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(collapseValue)))), - new SearchHit(2, "ID2", new Text("type"), - Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(collapseValue))))}, + Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(collapseValue))), + Collections.emptyMap()), new SearchHit(2, "ID2", new Text("type"), Collections.singletonMap("someField", + new DocumentField("someField", Collections.singletonList(collapseValue))), Collections.emptyMap())}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); InternalSearchResponse internalSearchResponse = new InternalSearchResponse(hits, null, null, null, false, null, 1); ExpandSearchPhase phase = new ExpandSearchPhase(mockSearchPhaseContext, internalSearchResponse, null); @@ -172,9 +172,9 @@ void sendExecuteMultiSearch(MultiSearchRequest request, SearchTask task, ActionL }; SearchHits hits = new SearchHits(new SearchHit[]{new SearchHit(1, "ID", new Text("type"), - Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(null)))), - new SearchHit(2, "ID2", new Text("type"), - Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(null))))}, + Collections.singletonMap("someField", new DocumentField("someField", Collections.singletonList(null))), + Collections.emptyMap()), new SearchHit(2, "ID2", new Text("type"), Collections.singletonMap("someField", + new DocumentField("someField", Collections.singletonList(null))), Collections.emptyMap())}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F); InternalSearchResponse internalSearchResponse = new InternalSearchResponse(hits, null, null, null, false, null, 1); ExpandSearchPhase phase = new ExpandSearchPhase(mockSearchPhaseContext, internalSearchResponse, null); diff --git a/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java b/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java index 158ad0ff2f3d3..42231a995676e 100644 --- a/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java @@ -321,7 +321,7 @@ private static AtomicArray generateFetchResults(int nShards, List searchHits = new ArrayList<>(); for (ScoreDoc scoreDoc : mergedSearchDocs) { if (scoreDoc.shardIndex == shardIndex) { - searchHits.add(new SearchHit(scoreDoc.doc, "", new Text(""), Collections.emptyMap())); + searchHits.add(new SearchHit(scoreDoc.doc, "", new Text(""), Collections.emptyMap(), Collections.emptyMap())); if (scoreDoc.score > maxScore) { maxScore = scoreDoc.score; } @@ -332,7 +332,7 @@ private static AtomicArray generateFetchResults(int nShards, for (CompletionSuggestion.Entry.Option option : ((CompletionSuggestion) suggestion).getOptions()) { ScoreDoc doc = option.getDoc(); if (doc.shardIndex == shardIndex) { - searchHits.add(new SearchHit(doc.doc, "", new Text(""), Collections.emptyMap())); + searchHits.add(new SearchHit(doc.doc, "", new Text(""), Collections.emptyMap(), Collections.emptyMap())); if (doc.score > maxScore) { maxScore = doc.score; } diff --git a/server/src/test/java/org/elasticsearch/action/search/SearchResponseTests.java b/server/src/test/java/org/elasticsearch/action/search/SearchResponseTests.java index 362fb6e6e4063..e9a85ac0d8832 100644 --- a/server/src/test/java/org/elasticsearch/action/search/SearchResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/SearchResponseTests.java @@ -208,7 +208,7 @@ public void testFromXContentWithFailures() throws IOException { } public void testToXContent() { - SearchHit hit = new SearchHit(1, "id1", new Text("type"), Collections.emptyMap()); + SearchHit hit = new SearchHit(1, "id1", new Text("type"), Collections.emptyMap(), Collections.emptyMap()); hit.score(2.0f); SearchHit[] hits = new SearchHit[] { hit }; { diff --git a/server/src/test/java/org/elasticsearch/search/SearchHitTests.java b/server/src/test/java/org/elasticsearch/search/SearchHitTests.java index 6234340061b48..ba33bf3cd0cda 100644 --- a/server/src/test/java/org/elasticsearch/search/SearchHitTests.java +++ b/server/src/test/java/org/elasticsearch/search/SearchHitTests.java @@ -73,14 +73,24 @@ public static SearchHit createTestItem(XContentType xContentType, boolean withOp if (randomBoolean()) { nestedIdentity = NestedIdentityTests.createTestItem(randomIntBetween(0, 2)); } - Map fields = null; + Map fields = new HashMap<>(); if (frequently()) { fields = new HashMap<>(); if (randomBoolean()) { fields = GetResultTests.randomDocumentFields(xContentType).v2(); } } - SearchHit hit = new SearchHit(internalId, uid, type, nestedIdentity, fields); + HashMap metaFields = new HashMap<>(); + HashMap documentFields = new HashMap<>(); + for (Map.Entry fieldEntry: fields.entrySet()) { + if (fieldEntry.getValue().isMetadataField()) { + metaFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } else { + documentFields.put(fieldEntry.getKey(), fieldEntry.getValue()); + } + } + + SearchHit hit = new SearchHit(internalId, uid, type, nestedIdentity, documentFields, metaFields); if (frequently()) { if (rarely()) { hit.score(Float.NaN); @@ -213,7 +223,7 @@ public void testFromXContentWithoutTypeAndId() throws IOException { } public void testToXContent() throws IOException { - SearchHit searchHit = new SearchHit(1, "id1", new Text("type"), Collections.emptyMap()); + SearchHit searchHit = new SearchHit(1, "id1", new Text("type"), Collections.emptyMap(), Collections.emptyMap()); searchHit.score(1.5f); XContentBuilder builder = JsonXContent.contentBuilder(); searchHit.toXContent(builder, ToXContent.EMPTY_PARAMS); @@ -226,25 +236,25 @@ public void testSerializeShardTarget() throws Exception { clusterAlias, OriginalIndices.NONE); Map innerHits = new HashMap<>(); - SearchHit innerHit1 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit innerHit1 = new SearchHit(0, "_id", new Text("_type"), null, null); innerHit1.shard(target); - SearchHit innerInnerHit2 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit innerInnerHit2 = new SearchHit(0, "_id", new Text("_type"), null, null); innerInnerHit2.shard(target); innerHits.put("1", new SearchHits(new SearchHit[]{innerInnerHit2}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1f)); innerHit1.setInnerHits(innerHits); - SearchHit innerHit2 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit innerHit2 = new SearchHit(0, "_id", new Text("_type"), null, null); innerHit2.shard(target); - SearchHit innerHit3 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit innerHit3 = new SearchHit(0, "_id", new Text("_type"), null, null); innerHit3.shard(target); innerHits = new HashMap<>(); - SearchHit hit1 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit hit1 = new SearchHit(0, "_id", new Text("_type"), null, null); innerHits.put("1", new SearchHits(new SearchHit[]{innerHit1, innerHit2}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1f)); innerHits.put("2", new SearchHits(new SearchHit[]{innerHit3}, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1f)); hit1.shard(target); hit1.setInnerHits(innerHits); - SearchHit hit2 = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit hit2 = new SearchHit(0, "_id", new Text("_type"), null, null); hit2.shard(target); SearchHits hits = new SearchHits(new SearchHit[]{hit1, hit2}, new TotalHits(2, TotalHits.Relation.EQUAL_TO), 1f); @@ -271,7 +281,7 @@ public void testSerializeShardTarget() throws Exception { } public void testNullSource() { - SearchHit searchHit = new SearchHit(0, "_id", new Text("_type"), null); + SearchHit searchHit = new SearchHit(0, "_id", new Text("_type"), null, null); assertThat(searchHit.getSourceAsMap(), nullValue()); assertThat(searchHit.getSourceRef(), nullValue()); diff --git a/server/src/test/java/org/elasticsearch/search/SearchHitsTests.java b/server/src/test/java/org/elasticsearch/search/SearchHitsTests.java index 9e87628d35d1c..a65c0601531d4 100644 --- a/server/src/test/java/org/elasticsearch/search/SearchHitsTests.java +++ b/server/src/test/java/org/elasticsearch/search/SearchHitsTests.java @@ -208,8 +208,8 @@ protected SearchHits doParseInstance(XContentParser parser) throws IOException { public void testToXContent() throws IOException { SearchHit[] hits = new SearchHit[] { - new SearchHit(1, "id1", new Text("type"), Collections.emptyMap()), - new SearchHit(2, "id2", new Text("type"), Collections.emptyMap()) }; + new SearchHit(1, "id1", new Text("type"), Collections.emptyMap(), Collections.emptyMap()), + new SearchHit(2, "id2", new Text("type"), Collections.emptyMap(), Collections.emptyMap()) }; long totalHits = 1000; float maxScore = 1.5f; @@ -226,9 +226,9 @@ public void testToXContent() throws IOException { public void testFromXContentWithShards() throws IOException { for (boolean withExplanation : new boolean[] {true, false}) { final SearchHit[] hits = new SearchHit[]{ - new SearchHit(1, "id1", new Text("type"), Collections.emptyMap()), - new SearchHit(2, "id2", new Text("type"), Collections.emptyMap()), - new SearchHit(10, "id10", new Text("type"), Collections.emptyMap()) + new SearchHit(1, "id1", new Text("type"), Collections.emptyMap(), Collections.emptyMap()), + new SearchHit(2, "id2", new Text("type"), Collections.emptyMap(), Collections.emptyMap()), + new SearchHit(10, "id10", new Text("type"), Collections.emptyMap(), Collections.emptyMap()) }; for (SearchHit hit : hits) { diff --git a/server/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalTopHitsTests.java b/server/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalTopHitsTests.java index 291c34dc4b5a2..25e03dc0e3716 100644 --- a/server/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalTopHitsTests.java +++ b/server/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalTopHitsTests.java @@ -50,6 +50,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -114,7 +115,7 @@ protected InternalTopHits createTestInstance(String name, List(1)); - hitContext.hit().getFields().put(NAME, hitField); + hitContext.hit().setField(NAME, hitField); } TermVectorsRequest termVectorsRequest = new TermVectorsRequest(context.indexShard().shardId().getIndex().getName(), hitContext.hit().getType(), hitContext.hit().getId()); diff --git a/server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhaseTests.java b/server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhaseTests.java index d87d21c7d0e5d..55543127b39c0 100644 --- a/server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhaseTests.java +++ b/server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhaseTests.java @@ -152,7 +152,7 @@ private FetchSubPhase.HitContext hitExecuteMultiple(XContentBuilder source, bool SearchContext searchContext = new FetchSourcePhaseTestSearchContext(fetchSourceContext, source == null ? null : BytesReference.bytes(source)); FetchSubPhase.HitContext hitContext = new FetchSubPhase.HitContext(); - final SearchHit searchHit = new SearchHit(1, null, null, nestedIdentity, null); + final SearchHit searchHit = new SearchHit(1, null, null, nestedIdentity, null, null); hitContext.reset(searchHit, null, 1, null); FetchSourcePhase phase = new FetchSourcePhase(); phase.hitExecute(searchContext, hitContext); diff --git a/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/EnrichShardMultiSearchAction.java b/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/EnrichShardMultiSearchAction.java index dc2426343d17c..7264ba923c868 100644 --- a/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/EnrichShardMultiSearchAction.java +++ b/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/EnrichShardMultiSearchAction.java @@ -261,7 +261,13 @@ protected MultiSearchResponse shardOperation(Request request, ShardId shardId) t visitor.reset(); searcher.doc(scoreDoc.doc, visitor); visitor.postProcess(mapperService); - final SearchHit hit = new SearchHit(scoreDoc.doc, visitor.uid().id(), typeText, Collections.emptyMap()); + final SearchHit hit = new SearchHit( + scoreDoc.doc, + visitor.uid().id(), + typeText, + Collections.emptyMap(), + Collections.emptyMap() + ); hit.sourceRef(filterSource(fetchSourceContext, visitor.source())); hits[j] = hit; } diff --git a/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/GeoMatchProcessorTests.java b/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/GeoMatchProcessorTests.java index d94c94b41f57d..863dcf455af02 100644 --- a/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/GeoMatchProcessorTests.java +++ b/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/GeoMatchProcessorTests.java @@ -176,6 +176,7 @@ public SearchResponse mockResponse(Map> documents) { randomInt(100), e.getKey(), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap() ); try (XContentBuilder builder = XContentBuilder.builder(XContentType.SMILE.xContent())) { diff --git a/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/MatchProcessorTests.java b/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/MatchProcessorTests.java index c7e26310deade..f3a27938aec34 100644 --- a/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/MatchProcessorTests.java +++ b/x-pack/plugin/enrich/src/test/java/org/elasticsearch/xpack/enrich/MatchProcessorTests.java @@ -386,6 +386,7 @@ public SearchResponse mockResponse(Map> documents) { randomInt(100), e.getKey().toString(), new Text(MapperService.SINGLE_MAPPING_NAME), + Collections.emptyMap(), Collections.emptyMap() ); try (XContentBuilder builder = XContentBuilder.builder(XContentType.SMILE.xContent())) { diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchResponseTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchResponseTests.java index 608134e87d9fb..36f5ff0c98619 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchResponseTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchResponseTests.java @@ -24,7 +24,7 @@ static List randomEvents() { if (randomBoolean()) { hits = new ArrayList<>(); for (int i = 0; i < size; i++) { - hits.add(new SearchHit(i, randomAlphaOfLength(10), null, new HashMap<>())); + hits.add(new SearchHit(i, randomAlphaOfLength(10), null, new HashMap<>(), new HashMap<>())); } } if (randomBoolean()) { diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/dataframe/process/DataFrameRowsJoinerTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/dataframe/process/DataFrameRowsJoinerTests.java index 6f672f412648d..6f3e0ff22e05f 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/dataframe/process/DataFrameRowsJoinerTests.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/dataframe/process/DataFrameRowsJoinerTests.java @@ -235,7 +235,8 @@ private void givenDataFrameBatches(List> batche } private static SearchHit newHit(String json) { - SearchHit hit = new SearchHit(randomInt(), randomAlphaOfLength(10), new Text("doc"), Collections.emptyMap()); + SearchHit hit = new SearchHit(randomInt(), randomAlphaOfLength(10), new Text("doc"), + Collections.emptyMap(), Collections.emptyMap()); hit.sourceRef(new BytesArray(json)); return hit; } diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java index 0f18d29979bdc..d869964c6dded 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java @@ -908,7 +908,7 @@ private static SearchResponse createSearchResponse(List> sou fields.put("field_1", new DocumentField("field_1", Collections.singletonList("foo"))); fields.put("field_2", new DocumentField("field_2", Collections.singletonList("foo"))); - SearchHit hit = new SearchHit(123, String.valueOf(map.hashCode()), new Text("foo"), fields) + SearchHit hit = new SearchHit(123, String.valueOf(map.hashCode()), new Text("foo"), fields, Collections.emptyMap()) .sourceRef(BytesReference.bytes(XContentFactory.jsonBuilder().map(_source))); list.add(hit); diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java index a2b628df85885..28b435610d3ec 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java @@ -39,6 +39,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -190,7 +191,7 @@ public MockClientBuilder prepareSearchFields(String indexName, List accessToken = (Map) sourceMap.get("access_token"); final Map userToken = (Map) accessToken.get("user_token"); - final SearchHit hit = new SearchHit(idx, "token_" + userToken.get("id"), null, null); + final SearchHit hit = new SearchHit(idx, "token_" + userToken.get("id"), null, null, null); hit.sourceRef(source); return hit; } catch (IOException e) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java index cdcd44e09576c..63e514390ef3e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java @@ -340,7 +340,7 @@ private SearchHit[] buildHits(List sourcePrivile final SearchHit[] hits = new SearchHit[sourcePrivileges.size()]; for (int i = 0; i < hits.length; i++) { final ApplicationPrivilegeDescriptor p = sourcePrivileges.get(i); - hits[i] = new SearchHit(i, "application-privilege_" + p.getApplication() + ":" + p.getName(), null, null); + hits[i] = new SearchHit(i, "application-privilege_" + p.getApplication() + ":" + p.getName(), null, null, null); hits[i].sourceRef(new BytesArray(Strings.toString(p))); } return hits; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java index dd4158080fea0..ec598b3a46b3c 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java @@ -95,8 +95,8 @@ public void testExtractDateValue() { private SearchHits searchHitsOf(Object value) { TotalHits totalHits = new TotalHits(10, TotalHits.Relation.EQUAL_TO); - return new SearchHits(new SearchHit[] {new SearchHit(1, "docId", null, - Collections.singletonMap("topHitsAgg", new DocumentField("field", Collections.singletonList(value))))}, + return new SearchHits(new SearchHit[] {new SearchHit(1, "docId", null, Collections.singletonMap("topHitsAgg", + new DocumentField("field", Collections.singletonList(value))), Collections.emptyMap())}, totalHits, 0.0f); } } diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/WatcherServiceTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/WatcherServiceTests.java index da67900ee18c9..2e74274e02067 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/WatcherServiceTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/WatcherServiceTests.java @@ -180,7 +180,7 @@ void stopExecutor() { SearchHit[] hits = new SearchHit[count]; for (int i = 0; i < count; i++) { String id = String.valueOf(i); - SearchHit hit = new SearchHit(1, id, new Text("watch"), Collections.emptyMap()); + SearchHit hit = new SearchHit(1, id, new Text("watch"), Collections.emptyMap(), Collections.emptyMap()); hit.version(1L); hit.shard(new SearchShardTarget("nodeId", new ShardId(watchIndex, 0), "whatever", OriginalIndices.NONE)); hits[i] = hit; diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/condition/CompareConditionSearchTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/condition/CompareConditionSearchTests.java index 8824af4a8762a..23e76a289c072 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/condition/CompareConditionSearchTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/condition/CompareConditionSearchTests.java @@ -76,7 +76,7 @@ public void testExecuteWithAggs() throws Exception { public void testExecuteAccessHits() throws Exception { CompareCondition condition = new CompareCondition("ctx.payload.hits.hits.0._score", CompareCondition.Op.EQ, 1, Clock.systemUTC()); - SearchHit hit = new SearchHit(0, "1", new Text("type"), null); + SearchHit hit = new SearchHit(0, "1", new Text("type"), null, null); hit.score(1f); hit.shard(new SearchShardTarget("a", new ShardId("a", "indexUUID", 0), null, OriginalIndices.NONE)); diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/execution/TriggeredWatchStoreTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/execution/TriggeredWatchStoreTests.java index dd994573f00e5..25a0e7e2857f4 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/execution/TriggeredWatchStoreTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/execution/TriggeredWatchStoreTests.java @@ -216,7 +216,7 @@ public void testFindTriggeredWatchesGoodCase() { when(searchResponse1.getSuccessfulShards()).thenReturn(1); when(searchResponse1.getTotalShards()).thenReturn(1); BytesArray source = new BytesArray("{}"); - SearchHit hit = new SearchHit(0, "first_foo", new Text(SINGLE_MAPPING_NAME), null); + SearchHit hit = new SearchHit(0, "first_foo", new Text(SINGLE_MAPPING_NAME), null, null); hit.version(1L); hit.shard(new SearchShardTarget("_node_id", new ShardId(index, 0), null, OriginalIndices.NONE)); hit.sourceRef(source); @@ -230,7 +230,7 @@ public void testFindTriggeredWatchesGoodCase() { }).when(client).execute(eq(SearchAction.INSTANCE), any(), any()); // First return a scroll response with a single hit and then with no hits - hit = new SearchHit(0, "second_foo", new Text(SINGLE_MAPPING_NAME), null); + hit = new SearchHit(0, "second_foo", new Text(SINGLE_MAPPING_NAME), null, null); hit.version(1L); hit.shard(new SearchShardTarget("_node_id", new ShardId(index, 0), null, OriginalIndices.NONE)); hit.sourceRef(source);