ExistsIT.java 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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", the "GNU Affero General Public License v3.0 only", and the "Server Side
  5. * Public License v 1"; you may not use this file except in compliance with, at
  6. * your election, the "Elastic License 2.0", the "GNU Affero General Public
  7. * License v3.0 only", or the "Server Side Public License, v 1".
  8. */
  9. package org.elasticsearch.search.query;
  10. import org.elasticsearch.action.explain.ExplainResponse;
  11. import org.elasticsearch.action.index.IndexRequestBuilder;
  12. import org.elasticsearch.common.Strings;
  13. import org.elasticsearch.index.query.QueryBuilders;
  14. import org.elasticsearch.search.SearchHit;
  15. import org.elasticsearch.test.ESIntegTestCase;
  16. import org.elasticsearch.xcontent.XContentBuilder;
  17. import org.elasticsearch.xcontent.XContentFactory;
  18. import org.elasticsearch.xcontent.json.JsonXContent;
  19. import java.util.ArrayList;
  20. import java.util.HashMap;
  21. import java.util.LinkedHashMap;
  22. import java.util.List;
  23. import java.util.Locale;
  24. import java.util.Map;
  25. import static java.util.Collections.emptyMap;
  26. import static java.util.Collections.singletonMap;
  27. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
  28. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
  29. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCountAndNoFailures;
  30. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
  31. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailuresAndResponse;
  32. public class ExistsIT extends ESIntegTestCase {
  33. // TODO: move this to a unit test somewhere...
  34. public void testEmptyIndex() throws Exception {
  35. createIndex("test");
  36. assertNoFailures(prepareSearch("test").setQuery(QueryBuilders.existsQuery("foo")));
  37. assertNoFailures(prepareSearch("test").setQuery(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("foo"))));
  38. }
  39. public void testExists() throws Exception {
  40. XContentBuilder mapping = XContentBuilder.builder(JsonXContent.jsonXContent)
  41. .startObject()
  42. .startObject("_doc")
  43. .startObject("properties")
  44. .startObject("foo")
  45. .field("type", "text")
  46. .endObject()
  47. .startObject("bar")
  48. .field("type", "object")
  49. .startObject("properties")
  50. .startObject("foo")
  51. .field("type", "text")
  52. .endObject()
  53. .startObject("bar")
  54. .field("type", "object")
  55. .startObject("properties")
  56. .startObject("bar")
  57. .field("type", "text")
  58. .endObject()
  59. .endObject()
  60. .endObject()
  61. .startObject("baz")
  62. .field("type", "long")
  63. .endObject()
  64. .endObject()
  65. .endObject()
  66. .startObject("vec")
  67. .field("type", "sparse_vector")
  68. .endObject()
  69. .endObject()
  70. .endObject()
  71. .endObject();
  72. assertAcked(indicesAdmin().prepareCreate("idx").setMapping(mapping));
  73. Map<String, Object> barObject = new HashMap<>();
  74. barObject.put("foo", "bar");
  75. barObject.put("bar", singletonMap("bar", "foo"));
  76. @SuppressWarnings({ "rawtypes", "unchecked" })
  77. final Map<String, Object>[] sources = new Map[] {
  78. // simple property
  79. singletonMap("foo", "bar"),
  80. // object fields
  81. singletonMap("bar", barObject),
  82. singletonMap("bar", singletonMap("baz", 42)),
  83. // sparse_vector field
  84. singletonMap("vec", singletonMap("6", 100)),
  85. // sparse_vector field
  86. singletonMap("vec", singletonMap("1", 100)),
  87. // empty doc
  88. emptyMap() };
  89. List<IndexRequestBuilder> reqs = new ArrayList<>();
  90. for (Map<String, Object> source : sources) {
  91. reqs.add(prepareIndex("idx").setSource(source));
  92. }
  93. // We do NOT index dummy documents, otherwise the type for these dummy documents
  94. // would have _field_names indexed while the current type might not which might
  95. // confuse the exists/missing parser at query time
  96. indexRandom(true, false, reqs);
  97. final Map<String, Integer> expected = new LinkedHashMap<>();
  98. expected.put("foo", 1);
  99. expected.put("f*", 1);
  100. expected.put("bar", 2);
  101. expected.put("bar.*", 2);
  102. expected.put("bar.foo", 1);
  103. expected.put("bar.bar", 1);
  104. expected.put("bar.bar.bar", 1);
  105. expected.put("foobar", 0);
  106. expected.put("vec", 2);
  107. final long numDocs = sources.length;
  108. assertNoFailuresAndResponse(prepareSearch("idx").setSize(sources.length), allDocs -> {
  109. assertHitCount(allDocs, numDocs);
  110. for (Map.Entry<String, Integer> entry : expected.entrySet()) {
  111. final String fieldName = entry.getKey();
  112. final int count = entry.getValue();
  113. // exists
  114. assertNoFailuresAndResponse(prepareSearch("idx").setQuery(QueryBuilders.existsQuery(fieldName)), response -> {
  115. try {
  116. assertEquals(
  117. String.format(
  118. Locale.ROOT,
  119. "exists(%s, %d) mapping: %s response: %s",
  120. fieldName,
  121. count,
  122. Strings.toString(mapping),
  123. response
  124. ),
  125. count,
  126. response.getHits().getTotalHits().value()
  127. );
  128. } catch (AssertionError e) {
  129. for (SearchHit searchHit : allDocs.getHits()) {
  130. final String index = searchHit.getIndex();
  131. final String id = searchHit.getId();
  132. final ExplainResponse explanation = client().prepareExplain(index, id)
  133. .setQuery(QueryBuilders.existsQuery(fieldName))
  134. .get();
  135. logger.info(
  136. "Explanation for [{}] / [{}] / [{}]: [{}]",
  137. fieldName,
  138. id,
  139. searchHit.getSourceAsString(),
  140. explanation.getExplanation()
  141. );
  142. }
  143. throw e;
  144. }
  145. });
  146. }
  147. });
  148. }
  149. public void testFieldAlias() throws Exception {
  150. XContentBuilder mapping = XContentFactory.jsonBuilder()
  151. .startObject()
  152. .startObject("_doc")
  153. .startObject("properties")
  154. .startObject("bar")
  155. .field("type", "long")
  156. .endObject()
  157. .startObject("foo")
  158. .field("type", "object")
  159. .startObject("properties")
  160. .startObject("bar")
  161. .field("type", "double")
  162. .endObject()
  163. .endObject()
  164. .endObject()
  165. .startObject("foo-bar")
  166. .field("type", "alias")
  167. .field("path", "foo.bar")
  168. .endObject()
  169. .endObject()
  170. .endObject()
  171. .endObject();
  172. assertAcked(prepareCreate("idx").setMapping(mapping));
  173. ensureGreen("idx");
  174. List<IndexRequestBuilder> indexRequests = new ArrayList<>();
  175. indexRequests.add(prepareIndex("idx").setSource(emptyMap()));
  176. indexRequests.add(prepareIndex("idx").setSource(emptyMap()));
  177. indexRequests.add(prepareIndex("idx").setSource("bar", 3));
  178. indexRequests.add(prepareIndex("idx").setSource("foo", singletonMap("bar", 2.718)));
  179. indexRequests.add(prepareIndex("idx").setSource("foo", singletonMap("bar", 6.283)));
  180. indexRandom(true, false, indexRequests);
  181. Map<String, Integer> expected = new LinkedHashMap<>();
  182. expected.put("foo.bar", 2);
  183. expected.put("foo-bar", 2);
  184. expected.put("foo*", 2);
  185. expected.put("*bar", 3);
  186. for (Map.Entry<String, Integer> entry : expected.entrySet()) {
  187. String fieldName = entry.getKey();
  188. int expectedCount = entry.getValue();
  189. assertHitCountAndNoFailures(prepareSearch("idx").setQuery(QueryBuilders.existsQuery(fieldName)), expectedCount);
  190. }
  191. }
  192. public void testFieldAliasWithNoDocValues() throws Exception {
  193. XContentBuilder mapping = XContentFactory.jsonBuilder()
  194. .startObject()
  195. .startObject("_doc")
  196. .startObject("properties")
  197. .startObject("foo")
  198. .field("type", "long")
  199. .field("doc_values", false)
  200. .endObject()
  201. .startObject("foo-alias")
  202. .field("type", "alias")
  203. .field("path", "foo")
  204. .endObject()
  205. .endObject()
  206. .endObject()
  207. .endObject();
  208. assertAcked(prepareCreate("idx").setMapping(mapping));
  209. ensureGreen("idx");
  210. List<IndexRequestBuilder> indexRequests = new ArrayList<>();
  211. indexRequests.add(prepareIndex("idx").setSource(emptyMap()));
  212. indexRequests.add(prepareIndex("idx").setSource(emptyMap()));
  213. indexRequests.add(prepareIndex("idx").setSource("foo", 3));
  214. indexRequests.add(prepareIndex("idx").setSource("foo", 43));
  215. indexRandom(true, false, indexRequests);
  216. assertHitCountAndNoFailures(prepareSearch("idx").setQuery(QueryBuilders.existsQuery("foo-alias")), 2L);
  217. }
  218. }