/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.search.query;
import org.elasticsearch.action.explain.ExplainResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.test.ESIntegTestCase;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
public class ExistsIT extends ESIntegTestCase {
// TODO: move this to a unit test somewhere...
public void testEmptyIndex() throws Exception {
createIndex("test");
SearchResponse resp = client().prepareSearch("test").setQuery(QueryBuilders.existsQuery("foo")).execute().actionGet();
assertSearchResponse(resp);
resp = client().prepareSearch("test").setQuery(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("foo"))).execute().actionGet();
assertSearchResponse(resp);
}
public void testExists() throws Exception {
XContentBuilder mapping = XContentBuilder.builder(JsonXContent.jsonXContent)
.startObject()
.startObject("type")
.startObject("properties")
.startObject("foo")
.field("type", "text")
.endObject()
.startObject("bar")
.field("type", "object")
.startObject("properties")
.startObject("foo")
.field("type", "text")
.endObject()
.startObject("bar")
.field("type", "object")
.startObject("properties")
.startObject("bar")
.field("type", "text")
.endObject()
.endObject()
.endObject()
.startObject("baz")
.field("type", "long")
.endObject()
.endObject()
.endObject()
.endObject()
.endObject()
.endObject();
assertAcked(client().admin().indices().prepareCreate("idx").addMapping("type", mapping));
Map<String, Object> barObject = new HashMap<>();
barObject.put("foo", "bar");
barObject.put("bar", singletonMap("bar", "foo"));
@SuppressWarnings("unchecked")
final Map<String, Object>[] sources = new Map[] {
// simple property
singletonMap("foo", "bar"),
// object fields
singletonMap("bar", barObject),
singletonMap("bar", singletonMap("baz", 42)),
// empty doc
emptyMap()
};
List<IndexRequestBuilder> reqs = new ArrayList<IndexRequestBuilder>();
for (Map<String, Object> source : sources) {
reqs.add(client().prepareIndex("idx", "type").setSource(source));
}
// We do NOT index dummy documents, otherwise the type for these dummy documents
// would have _field_names indexed while the current type might not which might
// confuse the exists/missing parser at query time
indexRandom(true, false, reqs);
final Map<String, Integer> expected = new LinkedHashMap<String, Integer>();
expected.put("foo", 1);
expected.put("f*", 1);
expected.put("bar", 2);
expected.put("bar.*", 2);
expected.put("bar.foo", 1);
expected.put("bar.bar", 1);
expected.put("bar.bar.bar", 1);
expected.put("foobar", 0);
final long numDocs = sources.length;
SearchResponse allDocs = client().prepareSearch("idx").setSize(sources.length).get();
assertSearchResponse(allDocs);
assertHitCount(allDocs, numDocs);
for (Map.Entry<String, Integer> entry : expected.entrySet()) {
final String fieldName = entry.getKey();
final int count = entry.getValue();
// exists
SearchResponse resp = client().prepareSearch("idx").setQuery(QueryBuilders.existsQuery(fieldName)).execute().actionGet();
assertSearchResponse(resp);
try {
assertEquals(String.format(Locale.ROOT, "exists(%s, %d) mapping: %s response: %s", fieldName, count, mapping.string(), resp), count, resp.getHits().getTotalHits());
} catch (AssertionError e) {
for (SearchHit searchHit : allDocs.getHits()) {
final String index = searchHit.getIndex();
final String type = searchHit.getType();
final String id = searchHit.getId();
final ExplainResponse explanation = client().prepareExplain(index, type, id).setQuery(QueryBuilders.existsQuery(fieldName)).get();
logger.info("Explanation for [{}] / [{}] / [{}]: [{}]", fieldName, id, searchHit.getSourceAsString(), explanation.getExplanation());
}
throw e;
}
}
}
}