PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/server/src/test/java/org/elasticsearch/action/search/FetchLookupFieldsPhaseTests.java

https://github.com/elasticsearch/elasticsearch
Java | 209 lines | 190 code | 11 blank | 8 comment | 7 complexity | e1f07715812571552e70a89dca4a8266 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
  3. * or more contributor license agreements. Licensed under the Elastic License
  4. * 2.0 and the Server Side Public License, v 1; you may not use this file except
  5. * in compliance with, at your election, the Elastic License 2.0 or the Server
  6. * Side Public License, v 1.
  7. */
  8. package org.elasticsearch.action.search;
  9. import org.apache.lucene.search.TotalHits;
  10. import org.elasticsearch.action.ActionListener;
  11. import org.elasticsearch.common.document.DocumentField;
  12. import org.elasticsearch.index.query.TermQueryBuilder;
  13. import org.elasticsearch.search.SearchHit;
  14. import org.elasticsearch.search.SearchHitTests;
  15. import org.elasticsearch.search.SearchHits;
  16. import org.elasticsearch.search.fetch.subphase.FieldAndFormat;
  17. import org.elasticsearch.search.fetch.subphase.LookupField;
  18. import org.elasticsearch.search.internal.InternalSearchResponse;
  19. import org.elasticsearch.test.ESTestCase;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.concurrent.atomic.AtomicBoolean;
  23. import static org.hamcrest.Matchers.contains;
  24. import static org.hamcrest.Matchers.containsInAnyOrder;
  25. import static org.hamcrest.Matchers.equalTo;
  26. import static org.hamcrest.Matchers.hasSize;
  27. import static org.hamcrest.Matchers.instanceOf;
  28. public class FetchLookupFieldsPhaseTests extends ESTestCase {
  29. public void testNoLookupField() {
  30. MockSearchPhaseContext searchPhaseContext = new MockSearchPhaseContext(1);
  31. searchPhaseContext.searchTransport = new SearchTransportService(null, null, null) {
  32. @Override
  33. void sendExecuteMultiSearch(MultiSearchRequest request, SearchTask task, ActionListener<MultiSearchResponse> listener) {
  34. throw new AssertionError("No lookup field");
  35. }
  36. };
  37. int numHits = randomIntBetween(0, 10);
  38. SearchHit[] searchHits = new SearchHit[randomIntBetween(0, 10)];
  39. for (int i = 0; i < searchHits.length; i++) {
  40. searchHits[i] = SearchHitTests.createTestItem(randomBoolean(), randomBoolean());
  41. }
  42. SearchHits hits = new SearchHits(searchHits, new TotalHits(numHits, TotalHits.Relation.EQUAL_TO), 1.0f);
  43. InternalSearchResponse searchResponse = new InternalSearchResponse(hits, null, null, null, false, null, 1);
  44. FetchLookupFieldsPhase phase = new FetchLookupFieldsPhase(searchPhaseContext, searchResponse, null);
  45. phase.run();
  46. searchPhaseContext.assertNoFailure();
  47. assertNotNull(searchPhaseContext.searchResponse.get());
  48. }
  49. public void testBasic() {
  50. MockSearchPhaseContext searchPhaseContext = new MockSearchPhaseContext(1);
  51. final AtomicBoolean requestSent = new AtomicBoolean();
  52. searchPhaseContext.searchTransport = new SearchTransportService(null, null, null) {
  53. @Override
  54. void sendExecuteMultiSearch(
  55. MultiSearchRequest multiSearchRequest,
  56. SearchTask task,
  57. ActionListener<MultiSearchResponse> listener
  58. ) {
  59. assertTrue(requestSent.compareAndSet(false, true));
  60. // send 4 requests for term_1, term_2, term_3, and unknown
  61. assertThat(multiSearchRequest.requests(), hasSize(4));
  62. for (SearchRequest r : multiSearchRequest.requests()) {
  63. assertNotNull(r.source());
  64. assertThat(r.source().query(), instanceOf(TermQueryBuilder.class));
  65. assertThat(r.source().size(), equalTo(1));
  66. }
  67. final List<String> queryTerms = multiSearchRequest.requests().stream().map(r -> {
  68. final TermQueryBuilder query = (TermQueryBuilder) r.source().query();
  69. return query.value().toString();
  70. }).sorted().toList();
  71. assertThat(queryTerms, equalTo(List.of("term_1", "term_2", "term_3", "xyz")));
  72. final MultiSearchResponse.Item[] responses = new MultiSearchResponse.Item[multiSearchRequest.requests().size()];
  73. for (int i = 0; i < responses.length; i++) {
  74. final SearchRequest r = multiSearchRequest.requests().get(i);
  75. final TermQueryBuilder query = (TermQueryBuilder) r.source().query();
  76. final Map<String, List<Object>> fields = switch (query.value().toString()) {
  77. case "term_1" -> Map.of("field_a", List.of("a1", "a2"), "field_b", List.of("b2"));
  78. case "term_2" -> Map.of("field_a", List.of("a2", "a3"), "field_b", List.of("b1"));
  79. case "term_3" -> Map.of("field_a", List.of("a2"), "field_b", List.of("b1", "b2"));
  80. case "xyz" -> null;
  81. default -> throw new AssertionError("unknown term value");
  82. };
  83. final SearchHits searchHits;
  84. if (fields != null) {
  85. final SearchHit hit = new SearchHit(randomInt(1000));
  86. fields.forEach((f, values) -> hit.setDocumentField(f, new DocumentField(f, values, List.of())));
  87. searchHits = new SearchHits(new SearchHit[] { hit }, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0f);
  88. } else {
  89. searchHits = new SearchHits(new SearchHit[0], new TotalHits(0, TotalHits.Relation.EQUAL_TO), 1.0f);
  90. }
  91. InternalSearchResponse internalSearchResponse = new InternalSearchResponse(
  92. searchHits,
  93. null,
  94. null,
  95. null,
  96. false,
  97. null,
  98. 1
  99. );
  100. responses[i] = new MultiSearchResponse.Item(
  101. new SearchResponse(
  102. internalSearchResponse,
  103. null,
  104. 1,
  105. 1,
  106. 0,
  107. randomNonNegativeLong(),
  108. ShardSearchFailure.EMPTY_ARRAY,
  109. SearchResponseTests.randomClusters(),
  110. null
  111. ),
  112. null
  113. );
  114. }
  115. listener.onResponse(new MultiSearchResponse(responses, randomNonNegativeLong()));
  116. }
  117. };
  118. SearchHit leftHit0 = new SearchHit(randomInt(100));
  119. final List<FieldAndFormat> fetchFields = List.of(new FieldAndFormat(randomAlphaOfLength(10), null));
  120. {
  121. leftHit0.setDocumentField(
  122. "lookup_field_1",
  123. new DocumentField(
  124. "lookup_field_1",
  125. List.of(),
  126. List.of(),
  127. List.of(
  128. new LookupField("test_index", new TermQueryBuilder("test_field", "term_1"), fetchFields, 1),
  129. new LookupField("test_index", new TermQueryBuilder("test_field", "term_2"), fetchFields, 1)
  130. )
  131. )
  132. );
  133. leftHit0.setDocumentField(
  134. "lookup_field_2",
  135. new DocumentField(
  136. "lookup_field_2",
  137. List.of(),
  138. List.of(),
  139. List.of(new LookupField("test_index", new TermQueryBuilder("test_field", "term_2"), fetchFields, 1))
  140. )
  141. );
  142. }
  143. SearchHit leftHit1 = new SearchHit(randomInt(100));
  144. {
  145. leftHit1.setDocumentField(
  146. "lookup_field_2",
  147. new DocumentField(
  148. "lookup_field_2",
  149. List.of(),
  150. List.of(),
  151. List.of(
  152. new LookupField("test_index", new TermQueryBuilder("test_field", "term_2"), fetchFields, 1),
  153. new LookupField("test_index", new TermQueryBuilder("test_field", "xyz"), fetchFields, 1)
  154. )
  155. )
  156. );
  157. leftHit1.setDocumentField(
  158. "lookup_field_3",
  159. new DocumentField(
  160. "lookup_field_3",
  161. List.of(),
  162. List.of(),
  163. List.of(new LookupField("test_index", new TermQueryBuilder("test_field", "term_3"), fetchFields, 1))
  164. )
  165. );
  166. }
  167. SearchHits searchHits = new SearchHits(new SearchHit[] { leftHit0, leftHit1 }, new TotalHits(2, TotalHits.Relation.EQUAL_TO), 1.0f);
  168. InternalSearchResponse searchResponse = new InternalSearchResponse(searchHits, null, null, null, false, null, 1);
  169. FetchLookupFieldsPhase phase = new FetchLookupFieldsPhase(searchPhaseContext, searchResponse, null);
  170. phase.run();
  171. assertTrue(requestSent.get());
  172. searchPhaseContext.assertNoFailure();
  173. assertNotNull(searchPhaseContext.searchResponse.get());
  174. assertSame(searchPhaseContext.searchResponse.get().getHits().getHits()[0], leftHit0);
  175. assertSame(searchPhaseContext.searchResponse.get().getHits().getHits()[1], leftHit1);
  176. assertFalse(leftHit0.hasLookupFields());
  177. assertThat(
  178. leftHit0.field("lookup_field_1").getValues(),
  179. containsInAnyOrder(
  180. Map.of("field_a", List.of("a1", "a2"), "field_b", List.of("b2")),
  181. Map.of("field_a", List.of("a2", "a3"), "field_b", List.of("b1"))
  182. )
  183. );
  184. assertThat(
  185. leftHit0.field("lookup_field_2").getValues(),
  186. contains(Map.of("field_a", List.of("a2", "a3"), "field_b", List.of("b1")))
  187. );
  188. assertFalse(leftHit1.hasLookupFields());
  189. assertThat(
  190. leftHit1.field("lookup_field_2").getValues(),
  191. contains(Map.of("field_a", List.of("a2", "a3"), "field_b", List.of("b1")))
  192. );
  193. assertThat(
  194. leftHit1.field("lookup_field_3").getValues(),
  195. contains(Map.of("field_a", List.of("a2"), "field_b", List.of("b1", "b2")))
  196. );
  197. }
  198. }