OpenSearch/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java
Michael McCandless cf2fb4ed0f Remove core delete-by-query implementation, to be replaced with a plugin
The current implementation is dangerous: it unexpectedly refreshes,
which can quickly cause an unhealthy index (segment explosion).  It
can also delete different documents on primary vs replicas, causing
inconsistent replicas.

For 2.0 we will replace this with an optional plugin that does a
scan/scroll search and then issues bulk delete requests.

Closes #10859
2015-04-28 16:09:04 -04:00

2570 lines
132 KiB
Java

/*
* 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.child;
import org.apache.lucene.util.LuceneTestCase;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.action.explain.ExplainResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.cache.filter.FilterCacheModule;
import org.elasticsearch.index.cache.filter.FilterCacheModule.FilterCacheSettings;
import org.elasticsearch.index.cache.filter.weighted.WeightedFilterCache;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.mapper.FieldMapper.Loading;
import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.HasChildFilterBuilder;
import org.elasticsearch.index.query.HasChildQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.search.child.ScoreType;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
import org.elasticsearch.search.aggregations.bucket.global.Global;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.collect.Maps.newHashMap;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.common.io.Streams.copyToStringFromClasspath;
import static org.elasticsearch.common.settings.ImmutableSettings.builder;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.FilterBuilders.boolFilter;
import static org.elasticsearch.index.query.FilterBuilders.hasParentFilter;
import static org.elasticsearch.index.query.FilterBuilders.matchAllFilter;
import static org.elasticsearch.index.query.FilterBuilders.notFilter;
import static org.elasticsearch.index.query.FilterBuilders.queryFilter;
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
import static org.elasticsearch.index.query.FilterBuilders.termsFilter;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
import static org.elasticsearch.index.query.QueryBuilders.filteredQuery;
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
import static org.elasticsearch.index.query.QueryBuilders.idsQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery;
import static org.elasticsearch.index.query.QueryBuilders.prefixQuery;
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.topChildrenQuery;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.factorFunction;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.scriptFunction;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAllSuccessful;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHit;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId;
import static org.hamcrest.Matchers.*;
/**
*
*/
@ClusterScope(scope = Scope.SUITE)
public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return ImmutableSettings.settingsBuilder().put(super.nodeSettings(nodeOrdinal))
// aggressive filter caching so that we can assert on the filter cache size
.put(FilterCacheModule.FilterCacheSettings.FILTER_CACHE_TYPE, WeightedFilterCache.class)
.put(FilterCacheSettings.FILTER_CACHE_EVERYTHING, true)
.build();
}
@Test
public void multiLevelChild() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent")
.addMapping("grandchild", "_parent", "type=child"));
ensureGreen();
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "c_value1").setParent("p1").get();
client().prepareIndex("test", "grandchild", "gc1").setSource("gc_field", "gc_value1")
.setParent("c1").setRouting("p1").get();
refresh();
SearchResponse searchResponse = client()
.prepareSearch("test")
.setQuery(
filteredQuery(
matchAllQuery(),
hasChildFilter(
"child",
filteredQuery(termQuery("c_field", "c_value1"),
hasChildFilter("grandchild", termQuery("gc_field", "gc_value1")))))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasParentFilter("parent", termFilter("p_field", "p_value1")))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasParentFilter("child", termFilter("c_field", "c_value1")))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("gc1"));
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent", termQuery("p_field", "p_value1"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("child", termQuery("c_field", "c_value1"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("gc1"));
}
@Test
// see #6722
public void test6722() throws ElasticsearchException, IOException {
assertAcked(prepareCreate("test")
.addMapping("foo")
.addMapping("test", "_parent", "type=foo"));
ensureGreen();
// index simple data
client().prepareIndex("test", "foo", "1").setSource("foo", 1).get();
client().prepareIndex("test", "test", "2").setSource("foo", 1).setParent("1").get();
refresh();
String query = copyToStringFromClasspath("/org/elasticsearch/search/child/bool-query-with-empty-clauses.json");
SearchResponse searchResponse = client().prepareSearch("test").setSource(query).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("2"));
}
@Test
// see #2744
public void test2744() throws ElasticsearchException, IOException {
assertAcked(prepareCreate("test")
.addMapping("foo")
.addMapping("test", "_parent", "type=foo"));
ensureGreen();
// index simple data
client().prepareIndex("test", "foo", "1").setSource("foo", 1).get();
client().prepareIndex("test", "test").setSource("foo", 1).setParent("1").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("test", matchQuery("foo", 1))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("1"));
}
@Test
public void simpleChildQuery() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
// TEST FETCHING _parent from child
SearchResponse searchResponse = client().prepareSearch("test").setQuery(idsQuery("child").ids("c1")).addFields("_parent").execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
assertThat(searchResponse.getHits().getAt(0).field("_parent").value().toString(), equalTo("p1"));
// TEST matching on parent
searchResponse = client().prepareSearch("test").setQuery(termQuery("_parent", "p1")).addFields("_parent").get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("c1"), equalTo("c2")));
assertThat(searchResponse.getHits().getAt(0).field("_parent").value().toString(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("c1"), equalTo("c2")));
assertThat(searchResponse.getHits().getAt(1).field("_parent").value().toString(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(queryStringQuery("_parent:p1")).addFields("_parent").get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("c1"), equalTo("c2")));
assertThat(searchResponse.getHits().getAt(0).field("_parent").value().toString(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("c1"), equalTo("c2")));
assertThat(searchResponse.getHits().getAt(1).field("_parent").value().toString(), equalTo("p1"));
// TOP CHILDREN QUERY
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))).execute()
.actionGet();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "blue")))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "red"))).execute()
.actionGet();
assertHitCount(searchResponse, 2l);
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
// HAS CHILD
searchResponse = client().prepareSearch("test").setQuery(randomHasChild("child", "c_field", "yellow"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(randomHasChild("child", "c_field", "blue")).execute()
.actionGet();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
searchResponse = client().prepareSearch("test").setQuery(randomHasChild("child", "c_field", "red")).get();
assertHitCount(searchResponse, 2l);
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
// HAS PARENT
searchResponse = client().prepareSearch("test")
.setQuery(randomHasParent("parent", "p_field", "p_value2")).get();
assertNoFailures(searchResponse);
assertHitCount(searchResponse, 2l);
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c3"));
assertThat(searchResponse.getHits().getAt(1).id(), equalTo("c4"));
searchResponse = client().prepareSearch("test")
.setQuery(randomHasParent("parent", "p_field", "p_value1")).get();
assertHitCount(searchResponse, 2l);
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
assertThat(searchResponse.getHits().getAt(1).id(), equalTo("c2"));
}
@Test
@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch/issues/9270")
public void testClearIdCacheBug() throws Exception {
// enforce lazy loading to make sure that p/c stats are not counted as part of field data
assertAcked(prepareCreate("test")
.setSettings(ImmutableSettings.builder().put(indexSettings())
.put("index.refresh_interval", -1)) // Disable automatic refresh, so that the _parent doesn't get warmed
.addMapping("parent", XContentFactory.jsonBuilder().startObject().startObject("parent")
.startObject("properties")
.startObject("p_field")
.field("type", "string")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, Loading.LAZY)
.endObject()
.endObject()
.endObject().endObject().endObject()));
ensureGreen();
client().prepareIndex("test", "parent", "p0").setSource("p_field", "p_value0").get();
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
refresh();
// No _parent field yet, there shouldn't be anything in the parent id cache
IndicesStatsResponse indicesStatsResponse = client().admin().indices()
.prepareStats("test").setIdCache(true).get();
assertThat(indicesStatsResponse.getTotal().getIdCache().getMemorySizeInBytes(), equalTo(0l));
// Now add mapping + children
client().admin().indices().preparePutMapping("test").setType("child")
.setSource(XContentFactory.jsonBuilder().startObject().startObject("child")
.startObject("_parent")
.field("type", "parent")
.endObject()
.startObject("properties")
.startObject("c_field")
.field("type", "string")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, Loading.LAZY)
.endObject()
.endObject()
.endObject().endObject().endObject())
.get();
// index simple data
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
indicesStatsResponse = client().admin().indices()
.prepareStats("test").setFieldData(true).get();
// automatic warm-up has populated the cache since it found a parent field mapper
assertThat(indicesStatsResponse.getTotal().getIdCache().getMemorySizeInBytes(), greaterThan(0l));
// Even though p/c is field data based the stats stay zero, because _parent field data field is kept
// track of under id cache stats memory wise for bwc
assertThat(indicesStatsResponse.getTotal().getFieldData().getMemorySizeInBytes(), equalTo(0l));
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "blue"))))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
indicesStatsResponse = client().admin().indices()
.prepareStats("test").setFieldData(true).get();
assertThat(indicesStatsResponse.getTotal().getIdCache().getMemorySizeInBytes(), greaterThan(0l));
assertThat(indicesStatsResponse.getTotal().getFieldData().getMemorySizeInBytes(), equalTo(0l));
ClearIndicesCacheResponse clearCacheResponse = client().admin().indices().prepareClearCache("test").setIdCache(true).get();
assertNoFailures(clearCacheResponse);
assertAllSuccessful(clearCacheResponse);
indicesStatsResponse = client().admin().indices()
.prepareStats("test").setFieldData(true).get();
assertThat(indicesStatsResponse.getTotal().getIdCache().getMemorySizeInBytes(), equalTo(0l));
assertThat(indicesStatsResponse.getTotal().getFieldData().getMemorySizeInBytes(), equalTo(0l));
}
@Test
// See: https://github.com/elasticsearch/elasticsearch/issues/3290
public void testCachingBug_withFqueryFilter() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
List<IndexRequestBuilder> builders = new ArrayList<>();
// index simple data
for (int i = 0; i < 10; i++) {
builders.add(client().prepareIndex("test", "parent", Integer.toString(i)).setSource("p_field", i));
}
indexRandom(randomBoolean(), builders);
builders.clear();
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 10; i++) {
builders.add(client().prepareIndex("test", "child", Integer.toString(i)).setSource("c_field", i).setParent("" + 0));
}
for (int i = 0; i < 10; i++) {
builders.add(client().prepareIndex("test", "child", Integer.toString(i + 10)).setSource("c_field", i + 10).setParent(Integer.toString(i)));
}
if (randomBoolean()) {
break; // randomly break out and dont' have deletes / updates
}
}
indexRandom(true, builders);
for (int i = 1; i <= 10; i++) {
logger.info("Round {}", i);
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(queryFilter(topChildrenQuery("child", matchAllQuery())).cache(true))).execute()
.actionGet();
assertNoFailures(searchResponse);
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(queryFilter(hasChildQuery("child", matchAllQuery()).scoreType("max")).cache(true)))
.get();
assertNoFailures(searchResponse);
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(queryFilter(hasParentQuery("parent", matchAllQuery()).scoreType("score")).cache(true)))
.get();
assertNoFailures(searchResponse);
}
}
@Test
public void testHasParentFilter() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
Map<String, Set<String>> parentToChildren = newHashMap();
// Childless parent
client().prepareIndex("test", "parent", "p0").setSource("p_field", "p0").get();
parentToChildren.put("p0", new HashSet<String>());
String previousParentId = null;
int numChildDocs = 32;
int numChildDocsPerParent = 0;
List<IndexRequestBuilder> builders = new ArrayList<>();
for (int i = 1; i <= numChildDocs; i++) {
if (previousParentId == null || i % numChildDocsPerParent == 0) {
previousParentId = "p" + i;
builders.add(client().prepareIndex("test", "parent", previousParentId).setSource("p_field", previousParentId));
numChildDocsPerParent++;
}
String childId = "c" + i;
builders.add(client().prepareIndex("test", "child", childId).setSource("c_field", childId).setParent(previousParentId));
if (!parentToChildren.containsKey(previousParentId)) {
parentToChildren.put(previousParentId, new HashSet<String>());
}
assertThat(parentToChildren.get(previousParentId).add(childId), is(true));
}
indexRandom(true, builders.toArray(new IndexRequestBuilder[builders.size()]));
assertThat(parentToChildren.isEmpty(), equalTo(false));
for (Map.Entry<String, Set<String>> parentToChildrenEntry : parentToChildren.entrySet()) {
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasParentFilter("parent", termQuery("p_field", parentToChildrenEntry.getKey()))))
.setSize(numChildDocsPerParent).get();
assertNoFailures(searchResponse);
Set<String> childIds = parentToChildrenEntry.getValue();
assertThat(searchResponse.getHits().totalHits(), equalTo((long) childIds.size()));
for (int i = 0; i < searchResponse.getHits().totalHits(); i++) {
assertThat(childIds.remove(searchResponse.getHits().getAt(i).id()), is(true));
assertThat(searchResponse.getHits().getAt(i).score(), is(1.0f));
}
assertThat(childIds.size(), is(0));
}
}
@Test
public void simpleChildQueryWithFlush() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data with flushes, so we have many segments
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().admin().indices().prepareFlush().get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().admin().indices().prepareFlush().get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().admin().indices().prepareFlush().get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().admin().indices().prepareFlush().get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().admin().indices().prepareFlush().get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
client().admin().indices().prepareFlush().get();
refresh();
// TOP CHILDREN QUERY
SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow")))
.get();
assertNoFailures(searchResponse);
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "blue"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "red"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
// HAS CHILD QUERY
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "yellow"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "blue"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "red"))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
// HAS CHILD FILTER
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "yellow")))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "blue"))))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "red"))))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
}
@Test
public void testScopedFacet() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
SearchResponse searchResponse = client()
.prepareSearch("test")
.setQuery(topChildrenQuery("child", boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow"))))
.addAggregation(AggregationBuilders.global("global").subAggregation(
AggregationBuilders.filter("filter").filter(boolFilter().should(termFilter("c_field", "red")).should(termFilter("c_field", "yellow"))).subAggregation(
AggregationBuilders.terms("facet1").field("c_field")))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1")));
Global global = searchResponse.getAggregations().get("global");
Filter filter = global.getAggregations().get("filter");
Terms termsFacet = filter.getAggregations().get("facet1");
assertThat(termsFacet.getBuckets().size(), equalTo(2));
assertThat(termsFacet.getBuckets().get(0).getKeyAsString(), equalTo("red"));
assertThat(termsFacet.getBuckets().get(0).getDocCount(), equalTo(2L));
assertThat(termsFacet.getBuckets().get(1).getKeyAsString(), equalTo("yellow"));
assertThat(termsFacet.getBuckets().get(1).getDocCount(), equalTo(1L));
}
@Test
public void testDeletedParent() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
// TOP CHILDREN QUERY
SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow")))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1\""));
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "yellow")))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1\""));
// update p1 and see what that we get updated values...
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1_updated").get();
client().admin().indices().prepareRefresh().get();
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1_updated\""));
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "yellow")))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1_updated\""));
}
@Test
public void testDfsSearchType() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuery().mustNot(hasChildQuery("child", boolQuery().should(queryStringQuery("c_field:*"))))).get();
assertNoFailures(searchResponse);
searchResponse = client().prepareSearch("test").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuery().mustNot(hasParentQuery("parent", boolQuery().should(queryStringQuery("p_field:*"))))).execute()
.actionGet();
assertNoFailures(searchResponse);
searchResponse = client().prepareSearch("test").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuery().mustNot(topChildrenQuery("child", boolQuery().should(queryStringQuery("c_field:*"))))).execute()
.actionGet();
assertNoFailures(searchResponse);
}
@Test
public void testFixAOBEIfTopChildrenIsWrappedInMusNotClause() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(boolQuery().mustNot(topChildrenQuery("child", boolQuery().should(queryStringQuery("c_field:*"))))).execute()
.actionGet();
assertNoFailures(searchResponse);
}
@Test
public void testTopChildrenReSearchBug() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
int numberOfParents = 4;
int numberOfChildrenPerParent = 123;
for (int i = 1; i <= numberOfParents; i++) {
String parentId = String.format(Locale.ROOT, "p%d", i);
client().prepareIndex("test", "parent", parentId).setSource("p_field", String.format(Locale.ROOT, "p_value%d", i)).execute()
.actionGet();
for (int j = 1; j <= numberOfChildrenPerParent; j++) {
client().prepareIndex("test", "child", String.format(Locale.ROOT, "%s_c%d", parentId, j))
.setSource("c_field1", parentId, "c_field2", i % 2 == 0 ? "even" : "not_even").setParent(parentId).execute()
.actionGet();
}
}
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field1", "p3")))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p3"));
searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field2", "even"))).execute()
.actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p4")));
assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p4")));
}
@Test
public void testHasChildAndHasParentFailWhenSomeSegmentsDontContainAnyParentOrChildDocs() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
client().prepareIndex("test", "child", "1").setParent("1").setSource("c_field", 1).get();
client().admin().indices().prepareFlush("test").get();
client().prepareIndex("test", "type1", "1").setSource("p_field", 1).get();
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasChildFilter("child", matchAllQuery()))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasParentFilter("parent", matchAllQuery()))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
}
@Test
public void testCountApiUsage() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
String parentId = "p1";
client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get();
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(topChildrenQuery("child", termQuery("c_field", "1")))
.get();
assertHitCount(countResponse, 1l);
countResponse = client().prepareCount("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max"))
.get();
assertHitCount(countResponse, 1l);
countResponse = client().prepareCount("test").setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score"))
.get();
assertHitCount(countResponse, 1l);
countResponse = client().prepareCount("test").setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "1"))))
.get();
assertHitCount(countResponse, 1l);
countResponse = client().prepareCount("test").setQuery(constantScoreQuery(hasParentFilter("parent", termQuery("p_field", "1"))))
.get();
assertHitCount(countResponse, 1l);
}
@Test
public void testExplainUsage() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
String parentId = "p1";
client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
.setExplain(true)
.setQuery(topChildrenQuery("child", termQuery("c_field", "1")))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), equalTo("not implemented yet..."));
searchResponse = client().prepareSearch("test")
.setExplain(true)
.setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), equalTo("not implemented yet..."));
searchResponse = client().prepareSearch("test")
.setExplain(true)
.setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), equalTo("not implemented yet..."));
ExplainResponse explainResponse = client().prepareExplain("test", "parent", parentId)
.setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max"))
.get();
assertThat(explainResponse.isExists(), equalTo(true));
assertThat(explainResponse.getExplanation().toString(), equalTo("1.0 = sum of:\n 1.0 = not implemented yet...\n 0.0 = match on required clause, product of:\n 0.0 = # clause\n 0.0 = Match on id 0\n"));
}
List<IndexRequestBuilder> createDocBuilders() {
List<IndexRequestBuilder> indexBuilders = new ArrayList<>();
// Parent 1 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("1").setIndex("test").setSource("p_field", "p_value1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("1").setIndex("test")
.setSource("c_field1", 1, "c_field2", 0).setParent("1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("2").setIndex("test")
.setSource("c_field1", 1, "c_field2", 0).setParent("1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("3").setIndex("test")
.setSource("c_field1", 2, "c_field2", 0).setParent("1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("4").setIndex("test")
.setSource("c_field1", 2, "c_field2", 0).setParent("1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("5").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1).setParent("1"));
indexBuilders.add(client().prepareIndex().setType("child").setId("6").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2).setParent("1"));
// Parent 2 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("2").setIndex("test").setSource("p_field", "p_value2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("7").setIndex("test")
.setSource("c_field1", 3, "c_field2", 0).setParent("2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("8").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1).setParent("2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("9").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1).setParent("p")); // why
// "p"????
indexBuilders.add(client().prepareIndex().setType("child").setId("10").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1).setParent("2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("11").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1).setParent("2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("12").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2).setParent("2"));
// Parent 3 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("3").setIndex("test")
.setSource("p_field1", "p_value3", "p_field2", 5));
indexBuilders.add(client().prepareIndex().setType("child").setId("13").setIndex("test")
.setSource("c_field1", 4, "c_field2", 0, "c_field3", 0).setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("14").setIndex("test")
.setSource("c_field1", 1, "c_field2", 1, "c_field3", 1).setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("15").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2, "c_field3", 2).setParent("3")); // why
// "p"????
indexBuilders.add(client().prepareIndex().setType("child").setId("16").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2, "c_field3", 3).setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("17").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2, "c_field3", 4).setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("18").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2, "c_field3", 5).setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child1").setId("1").setIndex("test")
.setSource("c_field1", 1, "c_field2", 2, "c_field3", 6).setParent("3"));
return indexBuilders;
}
@Test
public void testScoreForParentChildQueries_withFunctionScore() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent")
.addMapping("child1", "_parent", "type=parent"));
ensureGreen();
indexRandom(true, createDocBuilders().toArray(new IndexRequestBuilder[0]));
SearchResponse response = client()
.prepareSearch("test")
.setQuery(
QueryBuilders.hasChildQuery(
"child",
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0), scriptFunction("doc['c_field1'].value"))
.boostMode(CombineFunction.REPLACE.getName())).scoreType("sum")).get();
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("1"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(4f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(3f));
response = client()
.prepareSearch("test")
.setQuery(
QueryBuilders.hasChildQuery(
"child",
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0), scriptFunction("doc['c_field1'].value"))
.boostMode(CombineFunction.REPLACE.getName())).scoreType("max")).get();
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(4f));
assertThat(response.getHits().hits()[1].id(), equalTo("2"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("1"));
assertThat(response.getHits().hits()[2].score(), equalTo(2f));
response = client()
.prepareSearch("test")
.setQuery(
QueryBuilders.hasChildQuery(
"child",
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0), scriptFunction("doc['c_field1'].value"))
.boostMode(CombineFunction.REPLACE.getName())).scoreType("avg")).get();
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(4f));
assertThat(response.getHits().hits()[1].id(), equalTo("2"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("1"));
assertThat(response.getHits().hits()[2].score(), equalTo(1.5f));
response = client()
.prepareSearch("test")
.setQuery(
QueryBuilders.hasParentQuery(
"parent",
QueryBuilders.functionScoreQuery(matchQuery("p_field1", "p_value3"), scriptFunction("doc['p_field2'].value"))
.boostMode(CombineFunction.REPLACE.getName())).scoreType("score"))
.addSort(SortBuilders.fieldSort("c_field3")).addSort(SortBuilders.scoreSort()).get();
assertThat(response.getHits().totalHits(), equalTo(7l));
assertThat(response.getHits().hits()[0].id(), equalTo("13"));
assertThat(response.getHits().hits()[0].score(), equalTo(5f));
assertThat(response.getHits().hits()[1].id(), equalTo("14"));
assertThat(response.getHits().hits()[1].score(), equalTo(5f));
assertThat(response.getHits().hits()[2].id(), equalTo("15"));
assertThat(response.getHits().hits()[2].score(), equalTo(5f));
assertThat(response.getHits().hits()[3].id(), equalTo("16"));
assertThat(response.getHits().hits()[3].score(), equalTo(5f));
assertThat(response.getHits().hits()[4].id(), equalTo("17"));
assertThat(response.getHits().hits()[4].score(), equalTo(5f));
assertThat(response.getHits().hits()[5].id(), equalTo("18"));
assertThat(response.getHits().hits()[5].score(), equalTo(5f));
assertThat(response.getHits().hits()[6].id(), equalTo("1"));
assertThat(response.getHits().hits()[6].score(), equalTo(5f));
}
@Test
// https://github.com/elasticsearch/elasticsearch/issues/2536
public void testParentChildQueriesCanHandleNoRelevantTypesInIndex() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
SearchResponse response = client().prepareSearch("test")
.setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value"))).get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo(0l));
client().prepareIndex("test", "child1").setSource(jsonBuilder().startObject().field("text", "value").endObject()).setRefresh(true)
.get();
response = client().prepareSearch("test").setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value"))).get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = client().prepareSearch("test").setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value")).scoreType("max"))
.get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = client().prepareSearch("test").setQuery(QueryBuilders.hasParentQuery("child", matchQuery("text", "value"))).get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = client().prepareSearch("test").setQuery(QueryBuilders.hasParentQuery("child", matchQuery("text", "value")).scoreType("score"))
.get();
assertNoFailures(response);
assertThat(response.getHits().totalHits(), equalTo(0l));
}
@Test
public void testHasChildAndHasParentFilter_withFilter() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get();
client().admin().indices().prepareFlush("test").get();
client().prepareIndex("test", "type1", "3").setSource("p_field", "p_value1").get();
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasChildFilter("child", termFilter("c_field", 1)))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), hasParentFilter("parent", termFilter("p_field", 1)))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("2"));
}
@Test
public void testHasChildAndHasParentWrappedInAQueryFilter() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// query filter in case for p/c shouldn't execute per segment, but rather
client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
client().admin().indices().prepareFlush("test").setForce(true).get();
client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(hasChildQuery("child", matchQuery("c_field", 1))))).get();
assertSearchHit(searchResponse, 1, hasId("1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(topChildrenQuery("child", matchQuery("c_field", 1))))).get();
assertSearchHit(searchResponse, 1, hasId("1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(hasParentQuery("parent", matchQuery("p_field", 1))))).get();
assertSearchHit(searchResponse, 1, hasId("2"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(boolQuery().must(hasChildQuery("child", matchQuery("c_field", 1)))))).get();
assertSearchHit(searchResponse, 1, hasId("1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(boolQuery().must(topChildrenQuery("child", matchQuery("c_field", 1)))))).get();
assertSearchHit(searchResponse, 1, hasId("1"));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), queryFilter(boolQuery().must(hasParentQuery("parent", matchQuery("p_field", 1)))))).get();
assertSearchHit(searchResponse, 1, hasId("2"));
}
@Test
public void testHasChildAndHasParentWrappedInAQueryFilterShouldNeverGetCached() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(ImmutableSettings.builder().put("index.cache.filter.type", "weighted"))
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get();
refresh();
for (int i = 0; i < 10; i++) {
SearchResponse searchResponse = client().prepareSearch("test")
.setExplain(true)
.setQuery(constantScoreQuery(boolFilter()
.must(queryFilter(hasChildQuery("child", matchQuery("c_field", 1))))
.cache(true)
)).get();
assertSearchHit(searchResponse, 1, hasId("1"));
// Can't start with ConstantScore(cache(BooleanFilter(
assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), startsWith("ConstantScore(CustomQueryWrappingFilter("));
searchResponse = client().prepareSearch("test")
.setExplain(true)
.setQuery(constantScoreQuery(boolFilter()
.must(queryFilter(boolQuery().must(matchAllQuery()).must(hasChildQuery("child", matchQuery("c_field", 1)))))
.cache(true)
)).get();
assertSearchHit(searchResponse, 1, hasId("1"));
// Can't start with ConstantScore(cache(BooleanFilter(
assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), startsWith("ConstantScore(CustomQueryWrappingFilter("));
}
}
@Test
public void testSimpleQueryRewrite() throws Exception {
assertAcked(prepareCreate("test")
//top_children query needs at least 2 shards for the totalHits to be accurate
.setSettings(settingsBuilder()
.put(indexSettings())
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, between(2, DEFAULT_MAX_NUM_SHARDS)))
.addMapping("parent", "p_field", "type=string")
.addMapping("child", "_parent", "type=parent", "c_field", "type=string"));
ensureGreen();
// index simple data
int childId = 0;
for (int i = 0; i < 10; i++) {
String parentId = String.format(Locale.ROOT, "p%03d", i);
client().prepareIndex("test", "parent", parentId).setSource("p_field", parentId).get();
int j = childId;
for (; j < childId + 50; j++) {
String childUid = String.format(Locale.ROOT, "c%03d", j);
client().prepareIndex("test", "child", childUid).setSource("c_field", childUid).setParent(parentId).get();
}
childId = j;
}
refresh();
SearchType[] searchTypes = new SearchType[]{SearchType.QUERY_THEN_FETCH, SearchType.DFS_QUERY_THEN_FETCH};
for (SearchType searchType : searchTypes) {
SearchResponse searchResponse = client().prepareSearch("test").setSearchType(searchType)
.setQuery(hasChildQuery("child", prefixQuery("c_field", "c")).scoreType("max")).addSort("p_field", SortOrder.ASC)
.setSize(5).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(10L));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("p000"));
assertThat(searchResponse.getHits().hits()[1].id(), equalTo("p001"));
assertThat(searchResponse.getHits().hits()[2].id(), equalTo("p002"));
assertThat(searchResponse.getHits().hits()[3].id(), equalTo("p003"));
assertThat(searchResponse.getHits().hits()[4].id(), equalTo("p004"));
searchResponse = client().prepareSearch("test").setSearchType(searchType)
.setQuery(hasParentQuery("parent", prefixQuery("p_field", "p")).scoreType("score")).addSort("c_field", SortOrder.ASC)
.setSize(5).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(500L));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("c000"));
assertThat(searchResponse.getHits().hits()[1].id(), equalTo("c001"));
assertThat(searchResponse.getHits().hits()[2].id(), equalTo("c002"));
assertThat(searchResponse.getHits().hits()[3].id(), equalTo("c003"));
assertThat(searchResponse.getHits().hits()[4].id(), equalTo("c004"));
searchResponse = client().prepareSearch("test").setSearchType(searchType)
.setQuery(topChildrenQuery("child", prefixQuery("c_field", "c")).factor(10)).addSort("p_field", SortOrder.ASC).setSize(5)
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(10L));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("p000"));
assertThat(searchResponse.getHits().hits()[1].id(), equalTo("p001"));
assertThat(searchResponse.getHits().hits()[2].id(), equalTo("p002"));
assertThat(searchResponse.getHits().hits()[3].id(), equalTo("p003"));
assertThat(searchResponse.getHits().hits()[4].id(), equalTo("p004"));
}
}
@Test
// See also issue:
// https://github.com/elasticsearch/elasticsearch/issues/3144
public void testReIndexingParentAndChildDocuments() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "x").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "x").setParent("p2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(hasChildQuery("child", termQuery("c_field", "yellow")).scoreType("sum")).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1\""));
searchResponse = client()
.prepareSearch("test")
.setQuery(
boolQuery().must(matchQuery("c_field", "x")).must(
hasParentQuery("parent", termQuery("p_field", "p_value2")).scoreType("score"))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c3"));
assertThat(searchResponse.getHits().getAt(1).id(), equalTo("c4"));
// re-index
for (int i = 0; i < 10; i++) {
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "d" + i).setSource("c_field", "red").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "x").setParent("p2").get();
client().admin().indices().prepareRefresh("test").get();
}
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "yellow")).scoreType("sum"))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1\""));
searchResponse = client()
.prepareSearch("test")
.setQuery(
boolQuery().must(matchQuery("c_field", "x")).must(
hasParentQuery("parent", termQuery("p_field", "p_value2")).scoreType("score"))).get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
assertThat(searchResponse.getHits().getAt(0).id(), Matchers.anyOf(equalTo("c3"), equalTo("c4")));
assertThat(searchResponse.getHits().getAt(1).id(), Matchers.anyOf(equalTo("c3"), equalTo("c4")));
}
@Test
// See also issue:
// https://github.com/elasticsearch/elasticsearch/issues/3203
public void testHasChildQueryWithMinimumScore() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "x").setParent("p1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c3").setSource("c_field", "x").setParent("p2").get();
client().prepareIndex("test", "child", "c4").setSource("c_field", "x").setParent("p2").get();
client().prepareIndex("test", "child", "c5").setSource("c_field", "x").setParent("p2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", matchAllQuery()).scoreType("sum"))
.setMinScore(3) // Score needs to be 3 or above!
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2"));
assertThat(searchResponse.getHits().getAt(0).score(), equalTo(3.0f));
}
@Test
public void testParentFieldFilter() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(settingsBuilder().put(indexSettings())
.put("index.refresh_interval", -1))
.addMapping("parent")
.addMapping("child", "_parent", "type=parent")
.addMapping("child2", "_parent", "type=parent"));
ensureGreen();
// test term filter
SearchResponse response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "p1")))
.get();
assertHitCount(response, 0l);
client().prepareIndex("test", "some_type", "1").setSource("field", "value").get();
client().prepareIndex("test", "parent", "p1").setSource("p_field", "value").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "value").setParent("p1").get();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "p1"))).execute()
.actionGet();
assertHitCount(response, 0l);
refresh();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "parent#p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
client().prepareIndex("test", "parent2", "p1").setSource("p_field", "value").setRefresh(true).get();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termFilter("_parent", "parent#p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
// test terms filter
client().prepareIndex("test", "child2", "c1").setSource("c_field", "value").setParent("p1").get();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termsFilter("_parent", "p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termsFilter("_parent", "parent#p1"))).execute()
.actionGet();
assertHitCount(response, 1l);
refresh();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termsFilter("_parent", "p1"))).execute()
.actionGet();
assertHitCount(response, 2l);
refresh();
response = client().prepareSearch("test").setQuery(filteredQuery(matchAllQuery(), termsFilter("_parent", "p1", "p1"))).execute()
.actionGet();
assertHitCount(response, 2l);
response = client().prepareSearch("test")
.setQuery(filteredQuery(matchAllQuery(), termsFilter("_parent", "parent#p1", "parent2#p1"))).get();
assertHitCount(response, 2l);
}
@Test
public void testHasChildNotBeingCached() throws ElasticsearchException, IOException {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "parent", "p3").setSource("p_field", "p_value3").get();
client().prepareIndex("test", "parent", "p4").setSource("p_field", "p_value4").get();
client().prepareIndex("test", "parent", "p5").setSource("p_field", "p_value5").get();
client().prepareIndex("test", "parent", "p6").setSource("p_field", "p_value6").get();
client().prepareIndex("test", "parent", "p7").setSource("p_field", "p_value7").get();
client().prepareIndex("test", "parent", "p8").setSource("p_field", "p_value8").get();
client().prepareIndex("test", "parent", "p9").setSource("p_field", "p_value9").get();
client().prepareIndex("test", "parent", "p10").setSource("p_field", "p_value10").get();
client().prepareIndex("test", "child", "c1").setParent("p1").setSource("c_field", "blue").get();
client().admin().indices().prepareFlush("test").get();
client().admin().indices().prepareRefresh("test").get();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "blue")).cache(true)))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
client().prepareIndex("test", "child", "c2").setParent("p2").setSource("c_field", "blue").get();
client().admin().indices().prepareRefresh("test").get();
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "blue")).cache(true)))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
}
private QueryBuilder randomHasChild(String type, String field, String value) {
if (randomBoolean()) {
if (randomBoolean()) {
return constantScoreQuery(hasChildFilter(type, termQuery(field, value)));
} else {
return filteredQuery(matchAllQuery(), hasChildFilter(type, termQuery(field, value)));
}
} else {
return hasChildQuery(type, termQuery(field, value));
}
}
private QueryBuilder randomHasParent(String type, String field, String value) {
if (randomBoolean()) {
if (randomBoolean()) {
return constantScoreQuery(hasParentFilter(type, termQuery(field, value)));
} else {
return filteredQuery(matchAllQuery(), hasParentFilter(type, termQuery(field, value)));
}
} else {
return hasParentQuery(type, termQuery(field, value));
}
}
@Test
// Relates to bug: https://github.com/elasticsearch/elasticsearch/issues/3818
public void testHasChildQueryOnlyReturnsSingleChildType() {
assertAcked(prepareCreate("grandissue")
.addMapping("grandparent", "name", "type=string")
.addMapping("parent", "_parent", "type=grandparent")
.addMapping("child_type_one", "_parent", "type=parent")
.addMapping("child_type_two", "_parent", "type=parent"));
client().prepareIndex("grandissue", "grandparent", "1").setSource("name", "Grandpa").get();
client().prepareIndex("grandissue", "parent", "2").setParent("1").setSource("name", "Dana").get();
client().prepareIndex("grandissue", "child_type_one", "3").setParent("2").setRouting("1")
.setSource("name", "William")
.get();
client().prepareIndex("grandissue", "child_type_two", "4").setParent("2").setRouting("1")
.setSource("name", "Kate")
.get();
refresh();
SearchResponse searchResponse = client().prepareSearch("grandissue").setQuery(
boolQuery().must(
hasChildQuery(
"parent",
boolQuery().must(
hasChildQuery(
"child_type_one",
boolQuery().must(
queryStringQuery("name:William*").analyzeWildcard(true)
)
)
)
)
)
).get();
assertHitCount(searchResponse, 1l);
searchResponse = client().prepareSearch("grandissue").setQuery(
boolQuery().must(
hasChildQuery(
"parent",
boolQuery().must(
hasChildQuery(
"child_type_two",
boolQuery().must(
queryStringQuery("name:William*").analyzeWildcard(true)
)
)
)
)
)
).get();
assertHitCount(searchResponse, 0l);
}
@Test
public void indexChildDocWithNoParentMapping() throws ElasticsearchException, IOException {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child1"));
ensureGreen();
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1", "_parent", "bla").get();
try {
client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get();
fail();
} catch (ElasticsearchIllegalArgumentException e) {
assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured"));
}
try {
client().prepareIndex("test", "child2", "c2").setParent("p1").setSource("c_field", "blue").get();
fail();
} catch (ElasticsearchIllegalArgumentException e) {
assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured"));
}
refresh();
}
@Test
public void testAddingParentToExistingMapping() throws ElasticsearchException, IOException {
createIndex("test");
ensureGreen();
PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("child").setSource("number", "type=integer")
.get();
assertThat(putMappingResponse.isAcknowledged(), equalTo(true));
GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings("test").get();
Map<String, Object> mapping = getMappingsResponse.getMappings().get("test").get("child").getSourceAsMap();
assertThat(mapping.size(), greaterThanOrEqualTo(1)); // there are potentially some meta fields configured randomly
assertThat(mapping.get("properties"), notNullValue());
try {
// Adding _parent metadata field to existing mapping is prohibited:
client().admin().indices().preparePutMapping("test").setType("child").setSource(jsonBuilder().startObject().startObject("child")
.startObject("_parent").field("type", "parent").endObject()
.endObject().endObject()).get();
fail();
} catch (MergeMappingException e) {
assertThat(e.toString(), containsString("Merge failed with failures {[The _parent field's type option can't be changed: [null]->[parent]]}"));
}
}
@Test @Slow
// The SimpleIdReaderTypeCache#docById method used lget, which can't be used if a map is shared.
public void testTopChildrenBug_concurrencyIssue() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c1").setParent("p1").setSource("c_field", "blue").get();
client().prepareIndex("test", "child", "c2").setParent("p1").setSource("c_field", "red").get();
client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "red").get();
client().admin().indices().prepareRefresh("test").get();
int numThreads = 10;
final CountDownLatch latch = new CountDownLatch(numThreads);
final AtomicReference<AssertionError> holder = new AtomicReference<>();
Runnable r = new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 100; i++) {
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(topChildrenQuery("child", termQuery("c_field", "blue")))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch("test")
.setQuery(topChildrenQuery("child", termQuery("c_field", "red")))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
}
} catch (AssertionError error) {
holder.set(error);
} finally {
latch.countDown();
}
}
};
for (int i = 0; i < 10; i++) {
new Thread(r).start();
}
latch.await();
if (holder.get() != null) {
throw holder.get();
}
}
@Test
public void testHasChildQueryWithNestedInnerObjects() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent", "objects", "type=nested")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
client().prepareIndex("test", "parent", "p1")
.setSource(jsonBuilder().startObject().field("p_field", "1").startArray("objects")
.startObject().field("i_field", "1").endObject()
.startObject().field("i_field", "2").endObject()
.startObject().field("i_field", "3").endObject()
.startObject().field("i_field", "4").endObject()
.startObject().field("i_field", "5").endObject()
.startObject().field("i_field", "6").endObject()
.endArray().endObject())
.get();
client().prepareIndex("test", "parent", "p2")
.setSource(jsonBuilder().startObject().field("p_field", "2").startArray("objects")
.startObject().field("i_field", "1").endObject()
.startObject().field("i_field", "2").endObject()
.endArray().endObject())
.get();
client().prepareIndex("test", "child", "c1").setParent("p1").setSource("c_field", "blue").get();
client().prepareIndex("test", "child", "c2").setParent("p1").setSource("c_field", "red").get();
client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "red").get();
refresh();
String scoreMode = ScoreType.values()[getRandom().nextInt(ScoreType.values().length)].name().toLowerCase(Locale.ROOT);
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(QueryBuilders.hasChildQuery("child", termQuery("c_field", "blue")).scoreType(scoreMode), notFilter(termFilter("p_field", "3"))))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch("test")
.setQuery(filteredQuery(QueryBuilders.hasChildQuery("child", termQuery("c_field", "red")).scoreType(scoreMode), notFilter(termFilter("p_field", "3"))))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
}
@Test
public void testNamedFilters() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
String parentId = "p1";
client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "1")).queryName("test"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max").queryName("test"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score").queryName("test"))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "1")).filterName("test")))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasParentFilter("parent", termQuery("p_field", "1")).filterName("test")))
.get();
assertHitCount(searchResponse, 1l);
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
}
@Test
public void testParentChildQueriesNoParentType() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(settingsBuilder()
.put(indexSettings())
.put("index.refresh_interval", -1)));
ensureGreen();
String parentId = "p1";
client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
refresh();
try {
client().prepareSearch("test")
.setQuery(hasChildQuery("child", termQuery("c_field", "1")))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
try {
client().prepareSearch("test")
.setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max"))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
try {
client().prepareSearch("test")
.setPostFilter(hasChildFilter("child", termQuery("c_field", "1")))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
try {
client().prepareSearch("test")
.setQuery(topChildrenQuery("child", termQuery("c_field", "1")).score("max"))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
try {
client().prepareSearch("test")
.setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score"))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
try {
client().prepareSearch("test")
.setPostFilter(hasParentFilter("parent", termQuery("p_field", "1")))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
}
}
@Test
public void testAdd_ParentFieldAfterIndexingParentDocButBeforeIndexingChildDoc() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(settingsBuilder()
.put(indexSettings())
.put("index.refresh_interval", -1)));
ensureGreen();
String parentId = "p1";
client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
refresh();
assertAcked(client().admin()
.indices()
.preparePutMapping("test")
.setType("child")
.setSource("_parent", "type=parent"));
client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get();
client().admin().indices().prepareRefresh().get();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(hasChildQuery("child", termQuery("c_field", "1")))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, parentId);
searchResponse = client().prepareSearch("test")
.setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max"))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, parentId);
searchResponse = client().prepareSearch("test")
.setPostFilter(hasChildFilter("child", termQuery("c_field", "1")))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, parentId);
searchResponse = client().prepareSearch("test")
.setQuery(topChildrenQuery("child", termQuery("c_field", "1")).score("max"))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, parentId);
searchResponse = client().prepareSearch("test")
.setPostFilter(hasParentFilter("parent", termQuery("p_field", "1")))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, "c1");
searchResponse = client().prepareSearch("test")
.setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score"))
.get();
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, "c1");
}
@Test
public void testParentChildCaching() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(
settingsBuilder()
.put(indexSettings())
.put("index.refresh_interval", -1)
)
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
// index simple data
client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
client().prepareIndex("test", "child", "c1").setParent("p1").setSource("c_field", "blue").get();
client().prepareIndex("test", "child", "c2").setParent("p1").setSource("c_field", "red").get();
client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "red").get();
client().admin().indices().prepareOptimize("test").setMaxNumSegments(1).setFlush(true).get();
client().prepareIndex("test", "parent", "p3").setSource("p_field", "p_value3").get();
client().prepareIndex("test", "parent", "p4").setSource("p_field", "p_value4").get();
client().prepareIndex("test", "child", "c4").setParent("p3").setSource("c_field", "green").get();
client().prepareIndex("test", "child", "c5").setParent("p3").setSource("c_field", "blue").get();
client().prepareIndex("test", "child", "c6").setParent("p4").setSource("c_field", "blue").get();
client().admin().indices().prepareFlush("test").get();
client().admin().indices().prepareRefresh("test").get();
for (int i = 0; i < 2; i++) {
SearchResponse searchResponse = client().prepareSearch()
.setQuery(filteredQuery(matchAllQuery(), boolFilter()
.must(FilterBuilders.hasChildFilter("child", matchQuery("c_field", "red")))
.must(matchAllFilter())
.cache(true)))
.get();
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
}
client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "blue").get();
client().admin().indices().prepareRefresh("test").get();
SearchResponse searchResponse = client().prepareSearch()
.setQuery(filteredQuery(matchAllQuery(), boolFilter()
.must(FilterBuilders.hasChildFilter("child", matchQuery("c_field", "red")))
.must(matchAllFilter())
.cache(true)))
.get();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
}
@Test
public void testParentChildQueriesViaScrollApi() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
for (int i = 0; i < 10; i++) {
client().prepareIndex("test", "parent", "p" + i).setSource("{}").get();
client().prepareIndex("test", "child", "c" + i).setSource("{}").setParent("p" + i).get();
}
refresh();
QueryBuilder[] queries = new QueryBuilder[]{
hasChildQuery("child", matchAllQuery()),
filteredQuery(matchAllQuery(), hasChildFilter("child", matchAllQuery())),
hasParentQuery("parent", matchAllQuery()),
filteredQuery(matchAllQuery(), hasParentFilter("parent", matchAllQuery())),
topChildrenQuery("child", matchAllQuery()).factor(10)
};
for (QueryBuilder query : queries) {
SearchResponse scrollResponse = client().prepareSearch("test")
.setScroll(TimeValue.timeValueSeconds(30))
.setSize(1)
.addField("_id")
.setQuery(query)
.setSearchType("scan")
.execute()
.actionGet();
assertNoFailures(scrollResponse);
assertThat(scrollResponse.getHits().totalHits(), equalTo(10l));
int scannedDocs = 0;
do {
scrollResponse = client()
.prepareSearchScroll(scrollResponse.getScrollId())
.setScroll(TimeValue.timeValueSeconds(30)).get();
assertThat(scrollResponse.getHits().totalHits(), equalTo(10l));
scannedDocs += scrollResponse.getHits().getHits().length;
} while (scrollResponse.getHits().getHits().length > 0);
assertThat(scannedDocs, equalTo(10));
}
}
@Test
public void testValidateThatHasChildAndHasParentFilterAreNeverCached() throws Exception {
assertAcked(prepareCreate("test")
.setSettings(builder().put(indexSettings())
//we need 0 replicas here to make sure we always hit the very same shards
.put(SETTING_NUMBER_OF_REPLICAS, 0))
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
client().prepareIndex("test", "parent", "1").setSource("field", "value")
.get();
client().prepareIndex("test", "child", "1").setParent("1").setSource("field", "value")
.setRefresh(true)
.get();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(hasChildQuery("child", matchAllQuery()))
.get();
assertHitCount(searchResponse, 1l);
searchResponse = client().prepareSearch("test")
.setQuery(hasParentQuery("parent", matchAllQuery()))
.get();
assertHitCount(searchResponse, 1l);
// Internally the has_child and has_parent use filter for the type field, which end up in the filter cache,
// so by first checking how much they take by executing has_child and has_parent *query* we can set a base line
// for the filter cache size in this test.
IndicesStatsResponse statsResponse = client().admin().indices().prepareStats("test").clear().setFilterCache(true).get();
long initialCacheSize = statsResponse.getIndex("test").getTotal().getFilterCache().getMemorySizeInBytes();
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(matchAllQuery(), FilterBuilders.hasChildFilter("child", matchAllQuery()).cache(true)))
.get();
assertHitCount(searchResponse, 1l);
statsResponse = client().admin().indices().prepareStats("test").clear().setFilterCache(true).get();
assertThat(statsResponse.getIndex("test").getTotal().getFilterCache().getMemorySizeInBytes(), equalTo(initialCacheSize));
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(matchAllQuery(), FilterBuilders.hasParentFilter("parent", matchAllQuery()).cache(true)))
.get();
assertHitCount(searchResponse, 1l);
// filter cache should not contain any thing, b/c has_child and has_parent can't be cached.
statsResponse = client().admin().indices().prepareStats("test").clear().setFilterCache(true).get();
assertThat(statsResponse.getIndex("test").getTotal().getFilterCache().getMemorySizeInBytes(), equalTo(initialCacheSize));
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(
matchAllQuery(),
FilterBuilders.boolFilter().cache(true)
.must(FilterBuilders.matchAllFilter())
.must(FilterBuilders.hasChildFilter("child", matchAllQuery()).cache(true))
))
.get();
assertHitCount(searchResponse, 1l);
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(
matchAllQuery(),
FilterBuilders.boolFilter().cache(true)
.must(FilterBuilders.matchAllFilter())
.must(FilterBuilders.hasParentFilter("parent", matchAllQuery()).cache(true))
))
.get();
assertHitCount(searchResponse, 1l);
// filter cache should not contain any thing, b/c has_child and has_parent can't be cached.
statsResponse = client().admin().indices().prepareStats("test").clear().setFilterCache(true).get();
assertThat(statsResponse.getIndex("test").getTotal().getFilterCache().getMemorySizeInBytes(), equalTo(initialCacheSize));
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(
matchAllQuery(),
FilterBuilders.boolFilter().cache(true)
.must(FilterBuilders.termFilter("field", "value").cache(true))
.must(FilterBuilders.hasChildFilter("child", matchAllQuery()).cache(true))
))
.get();
assertHitCount(searchResponse, 1l);
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.filteredQuery(
matchAllQuery(),
FilterBuilders.boolFilter().cache(true)
.must(FilterBuilders.termFilter("field", "value").cache(true))
.must(FilterBuilders.hasParentFilter("parent", matchAllQuery()).cache(true))
))
.get();
assertHitCount(searchResponse, 1l);
// filter cache should not contain any thing, b/c has_child and has_parent can't be cached.
statsResponse = client().admin().indices().prepareStats("test").clear().setFilterCache(true).get();
assertThat(statsResponse.getIndex("test").getTotal().getFilterCache().getMemorySizeInBytes(), greaterThan(initialCacheSize));
}
// https://github.com/elasticsearch/elasticsearch/issues/5783
@Test
public void testQueryBeforeChildType() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("features")
.addMapping("posts", "_parent", "type=features")
.addMapping("specials"));
ensureGreen();
client().prepareIndex("test", "features", "1").setSource("field", "foo").get();
client().prepareIndex("test", "posts", "1").setParent("1").setSource("field", "bar").get();
refresh();
SearchResponse resp;
resp = client().prepareSearch("test")
.setSource("{\"query\": {\"has_child\": {\"type\": \"posts\", \"query\": {\"match\": {\"field\": \"bar\"}}}}}").get();
assertHitCount(resp, 1L);
// Now reverse the order for the type after the query
resp = client().prepareSearch("test")
.setSource("{\"query\": {\"has_child\": {\"query\": {\"match\": {\"field\": \"bar\"}}, \"type\": \"posts\"}}}").get();
assertHitCount(resp, 1L);
}
@Test
// https://github.com/elasticsearch/elasticsearch/issues/6256
public void testParentFieldInMultiMatchField() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("type1")
.addMapping("type2", "_parent", "type=type1")
);
ensureGreen();
client().prepareIndex("test", "type2", "1").setParent("1").setSource("field", "value").get();
refresh();
SearchResponse response = client().prepareSearch("test")
.setQuery(multiMatchQuery("1", "_parent"))
.get();
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().getAt(0).id(), equalTo("1"));
}
@Test
public void testTypeIsAppliedInHasParentInnerQuery() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
List<IndexRequestBuilder> indexRequests = new ArrayList<>();
indexRequests.add(client().prepareIndex("test", "parent", "1").setSource("field1", "a"));
indexRequests.add(client().prepareIndex("test", "child", "1").setParent("1").setSource("{}"));
indexRequests.add(client().prepareIndex("test", "child", "2").setParent("1").setSource("{}"));
indexRandom(true, indexRequests);
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasParentFilter("parent", notFilter(termFilter("field1", "a")))))
.get();
assertHitCount(searchResponse, 0l);
searchResponse = client().prepareSearch("test")
.setQuery(hasParentQuery("parent", constantScoreQuery(notFilter(termFilter("field1", "a")))))
.get();
assertHitCount(searchResponse, 0l);
searchResponse = client().prepareSearch("test")
.setQuery(constantScoreQuery(hasParentFilter("parent", termFilter("field1", "a"))))
.get();
assertHitCount(searchResponse, 2l);
searchResponse = client().prepareSearch("test")
.setQuery(hasParentQuery("parent", constantScoreQuery(termFilter("field1", "a"))))
.get();
assertHitCount(searchResponse, 2l);
}
private List<IndexRequestBuilder> createMinMaxDocBuilders() {
List<IndexRequestBuilder> indexBuilders = new ArrayList<>();
// Parent 1 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("1").setIndex("test").setSource("id",1));
indexBuilders.add(client().prepareIndex().setType("child").setId("10").setIndex("test")
.setSource("foo", "one").setParent("1"));
// Parent 2 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("2").setIndex("test").setSource("id",2));
indexBuilders.add(client().prepareIndex().setType("child").setId("11").setIndex("test")
.setSource("foo", "one").setParent("2"));
indexBuilders.add(client().prepareIndex().setType("child").setId("12").setIndex("test")
.setSource("foo", "one two").setParent("2"));
// Parent 3 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("3").setIndex("test").setSource("id",3));
indexBuilders.add(client().prepareIndex().setType("child").setId("13").setIndex("test")
.setSource("foo", "one").setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("14").setIndex("test")
.setSource("foo", "one two").setParent("3"));
indexBuilders.add(client().prepareIndex().setType("child").setId("15").setIndex("test")
.setSource("foo", "one two three").setParent("3"));
// Parent 4 and its children
indexBuilders.add(client().prepareIndex().setType("parent").setId("4").setIndex("test").setSource("id",4));
indexBuilders.add(client().prepareIndex().setType("child").setId("16").setIndex("test")
.setSource("foo", "one").setParent("4"));
indexBuilders.add(client().prepareIndex().setType("child").setId("17").setIndex("test")
.setSource("foo", "one two").setParent("4"));
indexBuilders.add(client().prepareIndex().setType("child").setId("18").setIndex("test")
.setSource("foo", "one two three").setParent("4"));
indexBuilders.add(client().prepareIndex().setType("child").setId("19").setIndex("test")
.setSource("foo", "one two three four").setParent("4"));
return indexBuilders;
}
private SearchResponse minMaxQuery(String scoreType, int minChildren, int maxChildren, int cutoff) throws SearchPhaseExecutionException {
return client()
.prepareSearch("test")
.setQuery(
QueryBuilders
.hasChildQuery(
"child",
QueryBuilders.functionScoreQuery(constantScoreQuery(FilterBuilders.termFilter("foo", "two"))).boostMode("replace").scoreMode("sum")
.add(FilterBuilders.matchAllFilter(), factorFunction(1))
.add(FilterBuilders.termFilter("foo", "three"), factorFunction(1))
.add(FilterBuilders.termFilter("foo", "four"), factorFunction(1))).scoreType(scoreType)
.minChildren(minChildren).maxChildren(maxChildren).setShortCircuitCutoff(cutoff))
.addSort("_score", SortOrder.DESC).addSort("id", SortOrder.ASC).get();
}
private SearchResponse minMaxFilter(int minChildren, int maxChildren, int cutoff) throws SearchPhaseExecutionException {
return client()
.prepareSearch("test")
.setQuery(
QueryBuilders.constantScoreQuery(FilterBuilders.hasChildFilter("child", termFilter("foo", "two"))
.minChildren(minChildren).maxChildren(maxChildren).setShortCircuitCutoff(cutoff)))
.addSort("id", SortOrder.ASC).setTrackScores(true).get();
}
@Test
public void testMinMaxChildren() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("parent", "id", "type=long")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
indexRandom(true, createMinMaxDocBuilders().toArray(new IndexRequestBuilder[0]));
SearchResponse response;
int cutoff = getRandom().nextInt(4);
// Score mode = NONE
response = minMaxQuery("none", 0, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("none", 1, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("none", 2, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("4"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxQuery("none", 3, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
response = minMaxQuery("none", 4, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = minMaxQuery("none", 0, 4, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("none", 0, 3, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("none", 0, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxQuery("none", 2, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
try {
response = minMaxQuery("none", 3, 2, cutoff);
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
}
// Score mode = SUM
response = minMaxQuery("sum", 0, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("sum", 1, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("sum", 2, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
response = minMaxQuery("sum", 3, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
response = minMaxQuery("sum", 4, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = minMaxQuery("sum", 0, 4, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("sum", 0, 3, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(6f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(3f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("sum", 0, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("2"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxQuery("sum", 2, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
try {
response = minMaxQuery("sum", 3, 2, cutoff);
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
}
// Score mode = MAX
response = minMaxQuery("max", 0, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(2f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("max", 1, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(2f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("max", 2, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(2f));
response = minMaxQuery("max", 3, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
response = minMaxQuery("max", 4, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = minMaxQuery("max", 0, 4, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(2f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("max", 0, 3, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(3f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(2f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("max", 0, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("2"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxQuery("max", 2, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
try {
response = minMaxQuery("max", 3, 2, cutoff);
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
}
// Score mode = AVG
response = minMaxQuery("avg", 0, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1.5f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("avg", 1, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1.5f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("avg", 2, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1.5f));
response = minMaxQuery("avg", 3, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
response = minMaxQuery("avg", 4, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = minMaxQuery("avg", 0, 4, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1.5f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("avg", 0, 3, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(2f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1.5f));
assertThat(response.getHits().hits()[2].id(), equalTo("2"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxQuery("avg", 0, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1.5f));
assertThat(response.getHits().hits()[1].id(), equalTo("2"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxQuery("avg", 2, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1.5f));
try {
response = minMaxQuery("avg", 3, 2, cutoff);
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
}
// HasChildFilter
response = minMaxFilter(0, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxFilter(1, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxFilter(2, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("4"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxFilter(3, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("4"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
response = minMaxFilter(4, 0, cutoff);
assertThat(response.getHits().totalHits(), equalTo(0l));
response = minMaxFilter(0, 4, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxFilter(0, 3, cutoff);
assertThat(response.getHits().totalHits(), equalTo(3l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
assertThat(response.getHits().hits()[2].id(), equalTo("4"));
assertThat(response.getHits().hits()[2].score(), equalTo(1f));
response = minMaxFilter(0, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(2l));
assertThat(response.getHits().hits()[0].id(), equalTo("2"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
assertThat(response.getHits().hits()[1].id(), equalTo("3"));
assertThat(response.getHits().hits()[1].score(), equalTo(1f));
response = minMaxFilter(2, 2, cutoff);
assertThat(response.getHits().totalHits(), equalTo(1l));
assertThat(response.getHits().hits()[0].id(), equalTo("3"));
assertThat(response.getHits().hits()[0].score(), equalTo(1f));
try {
response = minMaxFilter(3, 2, cutoff);
fail();
} catch (SearchPhaseExecutionException e) {
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
}
}
@Test
@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch/issues/9461")
public void testParentFieldToNonExistingType() {
assertAcked(prepareCreate("test").addMapping("parent").addMapping("child", "_parent", "type=parent2"));
client().prepareIndex("test", "parent", "1").setSource("{}").get();
client().prepareIndex("test", "child", "1").setParent("1").setSource("{}").get();
refresh();
try {
client().prepareSearch("test")
.setQuery(QueryBuilders.hasChildQuery("child", matchAllQuery()))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
}
SearchResponse response = client().prepareSearch("test")
.setQuery(QueryBuilders.hasParentQuery("parent", matchAllQuery()))
.get();
assertHitCount(response, 0);
try {
client().prepareSearch("test")
.setQuery(QueryBuilders.constantScoreQuery(FilterBuilders.hasChildFilter("child", matchAllQuery())))
.get();
fail();
} catch (SearchPhaseExecutionException e) {
}
response = client().prepareSearch("test")
.setQuery(QueryBuilders.constantScoreQuery(FilterBuilders.hasParentFilter("parent", matchAllQuery())))
.get();
assertHitCount(response, 0);
}
private static HasChildFilterBuilder hasChildFilter(String type, QueryBuilder queryBuilder) {
HasChildFilterBuilder hasChildFilterBuilder = FilterBuilders.hasChildFilter(type, queryBuilder);
hasChildFilterBuilder.setShortCircuitCutoff(randomInt(10));
return hasChildFilterBuilder;
}
private static HasChildFilterBuilder hasChildFilter(String type, FilterBuilder filterBuilder) {
HasChildFilterBuilder hasChildFilterBuilder = FilterBuilders.hasChildFilter(type, filterBuilder);
hasChildFilterBuilder.setShortCircuitCutoff(randomInt(10));
return hasChildFilterBuilder;
}
private static HasChildQueryBuilder hasChildQuery(String type, QueryBuilder queryBuilder) {
HasChildQueryBuilder hasChildQueryBuilder = QueryBuilders.hasChildQuery(type, queryBuilder);
hasChildQueryBuilder.setShortCircuitCutoff(randomInt(10));
return hasChildQueryBuilder;
}
}