summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartijn van Groningen <martijn.v.groningen@gmail.com>2017-06-02 14:34:20 +0200
committerMartijn van Groningen <martijn.v.groningen@gmail.com>2017-06-02 23:27:16 +0200
commit2a71a7bffc7ad1262cdf84554277653858c3b7f5 (patch)
tree8f10bfd683b66699a0a91aa1f7e869436d4eceb9
parenta32d1b91fa44c005ea41fa17323ea6bc65352092 (diff)
Change `has_child`, `has_parent` queries and `childen` aggregation to work with the new join field type and
at the same time maintaining support for the `_parent` meta field type. Relates to #20257
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java29
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java11
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java25
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java7
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java51
-rw-r--r--modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java33
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ChildrenIT.java282
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/LegacyChildrenIT.java41
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregatorTests.java44
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/query/ChildQuerySearchIT.java1154
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java4
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java2
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/query/InnerHitsIT.java4
-rw-r--r--modules/parent-join/src/test/java/org/elasticsearch/join/query/LegacyChildQuerySearchIT.java318
-rw-r--r--modules/parent-join/src/test/resources/rest-api-spec/test/11_parent_child.yml44
15 files changed, 1295 insertions, 754 deletions
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
index 35dc4eacbf..3560736e44 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
@@ -30,6 +30,8 @@ import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.ParentFieldMapper;
import org.elasticsearch.index.query.QueryParseContext;
+import org.elasticsearch.join.mapper.ParentIdFieldMapper;
+import org.elasticsearch.join.mapper.ParentJoinFieldMapper;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.support.FieldContext;
@@ -92,8 +94,30 @@ public class ChildrenAggregationBuilder
@Override
protected ValuesSourceConfig<WithOrdinals> resolveConfig(SearchContext context) {
ValuesSourceConfig<WithOrdinals> config = new ValuesSourceConfig<>(ValuesSourceType.BYTES);
- DocumentMapper childDocMapper = context.mapperService().documentMapper(childType);
+ if (context.mapperService().getIndexSettings().isSingleType()) {
+ joinFieldResolveConfig(context, config);
+ } else {
+ parentFieldResolveConfig(context, config);
+ }
+ return config;
+ }
+
+ private void joinFieldResolveConfig(SearchContext context, ValuesSourceConfig<WithOrdinals> config) {
+ ParentJoinFieldMapper parentJoinFieldMapper = ParentJoinFieldMapper.getMapper(context.mapperService());
+ ParentIdFieldMapper parentIdFieldMapper = parentJoinFieldMapper.getParentIdFieldMapper(childType, false);
+ if (parentIdFieldMapper != null) {
+ parentFilter = parentIdFieldMapper.getParentFilter();
+ childFilter = parentIdFieldMapper.getChildFilter(childType);
+ MappedFieldType fieldType = parentIdFieldMapper.fieldType();
+ final SortedSetDVOrdinalsIndexFieldData fieldData = context.fieldData().getForField(fieldType);
+ config.fieldContext(new FieldContext(fieldType.name(), fieldData, fieldType));
+ } else {
+ config.unmapped(true);
+ }
+ }
+ private void parentFieldResolveConfig(SearchContext context, ValuesSourceConfig<WithOrdinals> config) {
+ DocumentMapper childDocMapper = context.mapperService().documentMapper(childType);
if (childDocMapper != null) {
ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper();
if (!parentFieldMapper.active()) {
@@ -107,14 +131,13 @@ public class ChildrenAggregationBuilder
MappedFieldType parentFieldType = parentDocMapper.parentFieldMapper().getParentJoinFieldType();
final SortedSetDVOrdinalsIndexFieldData fieldData = context.fieldData().getForField(parentFieldType);
config.fieldContext(new FieldContext(parentFieldType.name(), fieldData,
- parentFieldType));
+ parentFieldType));
} else {
config.unmapped(true);
}
} else {
config.unmapped(true);
}
- return config;
}
@Override
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java
index 43608e9b54..db9fae9b47 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java
@@ -40,7 +40,7 @@ import java.util.List;
* This class is also used to quickly retrieve the parent-join field defined in a mapping without
* specifying the name of the field.
*/
-class MetaJoinFieldMapper extends FieldMapper {
+public class MetaJoinFieldMapper extends FieldMapper {
static final String NAME = "_parent_join";
static final String CONTENT_TYPE = "parent_join";
@@ -68,8 +68,9 @@ class MetaJoinFieldMapper extends FieldMapper {
}
}
- static final class MetaJoinFieldType extends StringFieldType {
- ParentJoinFieldMapper mapper;
+ public static class MetaJoinFieldType extends StringFieldType {
+
+ private ParentJoinFieldMapper mapper;
MetaJoinFieldType() {}
@@ -100,6 +101,10 @@ class MetaJoinFieldMapper extends FieldMapper {
BytesRef binaryValue = (BytesRef) value;
return binaryValue.utf8ToString();
}
+
+ public ParentJoinFieldMapper getMapper() {
+ return mapper;
+ }
}
MetaJoinFieldMapper(String name, MappedFieldType fieldType, Settings indexSettings) {
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java
index 7a042eae84..cc2815c373 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java
@@ -23,6 +23,12 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
@@ -47,7 +53,7 @@ public final class ParentIdFieldMapper extends FieldMapper {
static final String CONTENT_TYPE = "parent";
static class Defaults {
- public static final MappedFieldType FIELD_TYPE = new ParentIdFieldType();
+ static final MappedFieldType FIELD_TYPE = new ParentIdFieldType();
static {
FIELD_TYPE.setTokenized(false);
@@ -86,7 +92,7 @@ public final class ParentIdFieldMapper extends FieldMapper {
}
public static final class ParentIdFieldType extends StringFieldType {
- public ParentIdFieldType() {
+ ParentIdFieldType() {
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
}
@@ -145,6 +151,9 @@ public final class ParentIdFieldMapper extends FieldMapper {
return parentName;
}
+ public Query getParentFilter() {
+ return new TermQuery(new Term(name().substring(0, name().indexOf('#')), parentName));
+ }
/**
* Returns the children names associated with this mapper.
*/
@@ -152,6 +161,18 @@ public final class ParentIdFieldMapper extends FieldMapper {
return children;
}
+ public Query getChildFilter(String type) {
+ return new TermQuery(new Term(name().substring(0, name().indexOf('#')), type));
+ }
+
+ public Query getChildrenFilter() {
+ BooleanQuery.Builder builder = new BooleanQuery.Builder();
+ for (String child : children) {
+ builder.add(getChildFilter(child), BooleanClause.Occur.SHOULD);
+ }
+ return new ConstantScoreQuery(builder.build());
+ }
+
@Override
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
if (context.externalValueSet() == false) {
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java
index d9c12d85c1..ecabbb096e 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java
@@ -81,7 +81,7 @@ public final class ParentJoinFieldMapper extends FieldMapper {
public static ParentJoinFieldMapper getMapper(MapperService service) {
MetaJoinFieldMapper.MetaJoinFieldType fieldType =
(MetaJoinFieldMapper.MetaJoinFieldType) service.fullName(MetaJoinFieldMapper.NAME);
- return fieldType == null ? null : fieldType.mapper;
+ return fieldType == null ? null : fieldType.getMapper();
}
private static String getParentIdFieldName(String joinFieldName, String parentName) {
@@ -121,11 +121,11 @@ public final class ParentJoinFieldMapper extends FieldMapper {
}
}
- static class Builder extends FieldMapper.Builder<Builder, ParentJoinFieldMapper> {
+ public static class Builder extends FieldMapper.Builder<Builder, ParentJoinFieldMapper> {
final List<ParentIdFieldMapper.Builder> parentIdFieldBuilders = new ArrayList<>();
boolean eagerGlobalOrdinals = true;
- Builder(String name) {
+ public Builder(String name) {
super(name, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE);
builder = this;
}
@@ -431,4 +431,5 @@ public final class ParentJoinFieldMapper extends FieldMapper {
}
}
}
+
}
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
index f574236b35..6485b8f649 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
@@ -49,6 +49,8 @@ import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryRewriteContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException;
+import org.elasticsearch.join.mapper.ParentIdFieldMapper;
+import org.elasticsearch.join.mapper.ParentJoinFieldMapper;
import java.io.IOException;
import java.util.HashMap;
@@ -305,6 +307,34 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
+ if (context.getIndexSettings().isSingleType()) {
+ return joinFieldDoToQuery(context);
+ } else {
+ return parentFieldDoToQuery(context);
+ }
+ }
+
+ private Query joinFieldDoToQuery(QueryShardContext context) throws IOException {
+ ParentJoinFieldMapper joinFieldMapper = ParentJoinFieldMapper.getMapper(context.getMapperService());
+ ParentIdFieldMapper parentIdFieldMapper = joinFieldMapper.getParentIdFieldMapper(type, false);
+ if (parentIdFieldMapper != null) {
+ Query parentFilter = parentIdFieldMapper.getParentFilter();
+ Query childFilter = parentIdFieldMapper.getChildFilter(type);
+ Query innerQuery = Queries.filtered(query.toQuery(context), childFilter);
+ MappedFieldType fieldType = parentIdFieldMapper.fieldType();
+ final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(fieldType);
+ return new LateParsingQuery(parentFilter, innerQuery, minChildren(), maxChildren(),
+ fieldType.name(), scoreMode, fieldData, context.getSearchSimilarity());
+ } else {
+ if (ignoreUnmapped) {
+ return new MatchNoDocsQuery();
+ } else {
+ throw new QueryShardException(context, "[" + NAME + "] join field has no parent type configured");
+ }
+ }
+ }
+
+ private Query parentFieldDoToQuery(QueryShardContext context) throws IOException {
Query innerQuery;
final String[] previousTypes = context.getTypes();
context.setTypes(type);
@@ -313,8 +343,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
} finally {
context.setTypes(previousTypes);
}
-
- DocumentMapper childDocMapper = context.documentMapper(type);
+ DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
if (childDocMapper == null) {
if (ignoreUnmapped) {
return new MatchNoDocsQuery();
@@ -330,16 +359,17 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
DocumentMapper parentDocMapper = context.getMapperService().documentMapper(parentType);
if (parentDocMapper == null) {
throw new QueryShardException(context,
- "[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]");
+ "[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]");
}
// wrap the query with type query
innerQuery = Queries.filtered(innerQuery, childDocMapper.typeFilter(context));
+ String joinField = ParentFieldMapper.joinField(parentType);
final MappedFieldType parentFieldType = parentDocMapper.parentFieldMapper().getParentJoinFieldType();
final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(parentFieldType);
return new LateParsingQuery(parentDocMapper.typeFilter(context), innerQuery, minChildren(), maxChildren(),
- parentType, scoreMode, fieldData, context.getSearchSimilarity());
+ joinField, scoreMode, fieldData, context.getSearchSimilarity());
}
/**
@@ -358,19 +388,19 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
private final Query innerQuery;
private final int minChildren;
private final int maxChildren;
- private final String parentType;
+ private final String joinField;
private final ScoreMode scoreMode;
private final SortedSetDVOrdinalsIndexFieldData fieldDataJoin;
private final Similarity similarity;
LateParsingQuery(Query toQuery, Query innerQuery, int minChildren, int maxChildren,
- String parentType, ScoreMode scoreMode,
+ String joinField, ScoreMode scoreMode,
SortedSetDVOrdinalsIndexFieldData fieldData, Similarity similarity) {
this.toQuery = toQuery;
this.innerQuery = innerQuery;
this.minChildren = minChildren;
this.maxChildren = maxChildren;
- this.parentType = parentType;
+ this.joinField = joinField;
this.scoreMode = scoreMode;
this.fieldDataJoin = fieldData;
this.similarity = similarity;
@@ -383,7 +413,6 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
return rewritten;
}
if (reader instanceof DirectoryReader) {
- String joinField = ParentFieldMapper.joinField(parentType);
IndexSearcher indexSearcher = new IndexSearcher(reader);
indexSearcher.setQueryCache(null);
indexSearcher.setSimilarity(similarity);
@@ -414,18 +443,18 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
if (maxChildren != that.maxChildren) return false;
if (!toQuery.equals(that.toQuery)) return false;
if (!innerQuery.equals(that.innerQuery)) return false;
- if (!parentType.equals(that.parentType)) return false;
+ if (!joinField.equals(that.joinField)) return false;
return scoreMode == that.scoreMode;
}
@Override
public int hashCode() {
- return Objects.hash(classHash(), toQuery, innerQuery, minChildren, maxChildren, parentType, scoreMode);
+ return Objects.hash(getClass(), toQuery, innerQuery, minChildren, maxChildren, joinField, scoreMode);
}
@Override
public String toString(String s) {
- return "LateParsingQuery {parentType=" + parentType + "}";
+ return "LateParsingQuery {joinField=" + joinField + "}";
}
public int getMinChildren() {
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
index 7bcbf7c611..3d23fac01b 100644
--- a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
@@ -55,6 +55,8 @@ import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryRewriteContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException;
+import org.elasticsearch.join.mapper.ParentIdFieldMapper;
+import org.elasticsearch.join.mapper.ParentJoinFieldMapper;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.fetch.subphase.InnerHitsContext;
@@ -187,6 +189,35 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
+ if (context.getIndexSettings().isSingleType()) {
+ return joinFieldDoToQuery(context);
+ } else {
+ return parentFieldDoToQuery(context);
+ }
+ }
+
+ private Query joinFieldDoToQuery(QueryShardContext context) throws IOException {
+ ParentJoinFieldMapper joinFieldMapper = ParentJoinFieldMapper.getMapper(context.getMapperService());
+ ParentIdFieldMapper parentIdFieldMapper = joinFieldMapper.getParentIdFieldMapper(type, true);
+ if (parentIdFieldMapper != null) {
+ Query parentFilter = parentIdFieldMapper.getParentFilter();
+ Query innerQuery = Queries.filtered(query.toQuery(context), parentFilter);
+ Query childFilter = parentIdFieldMapper.getChildrenFilter();
+ MappedFieldType fieldType = parentIdFieldMapper.fieldType();
+ final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(fieldType);
+ return new HasChildQueryBuilder.LateParsingQuery(childFilter, innerQuery,
+ HasChildQueryBuilder.DEFAULT_MIN_CHILDREN, HasChildQueryBuilder.DEFAULT_MAX_CHILDREN,
+ fieldType.name(), score ? ScoreMode.Max : ScoreMode.None, fieldData, context.getSearchSimilarity());
+ } else {
+ if (ignoreUnmapped) {
+ return new MatchNoDocsQuery();
+ } else {
+ throw new QueryShardException(context, "[" + NAME + "] join field has no parent type configured");
+ }
+ }
+ }
+
+ private Query parentFieldDoToQuery(QueryShardContext context) throws IOException {
Query innerQuery;
String[] previousTypes = context.getTypes();
context.setTypes(type);
@@ -239,7 +270,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
innerQuery,
HasChildQueryBuilder.DEFAULT_MIN_CHILDREN,
HasChildQueryBuilder.DEFAULT_MAX_CHILDREN,
- type,
+ ParentFieldMapper.joinField(type),
score ? ScoreMode.Max : ScoreMode.None,
fieldData,
context.getSearchSimilarity());
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ChildrenIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ChildrenIT.java
index 1b67b2a22b..eb9952c150 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ChildrenIT.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ChildrenIT.java
@@ -25,7 +25,6 @@ import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.join.ParentJoinPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.SearchHit;
@@ -84,15 +83,58 @@ public class ChildrenIT extends ESIntegTestCase {
return nodePlugins();
}
+ protected boolean legacy() {
+ return false;
+ }
+
+ private IndexRequestBuilder createIndexRequest(String index, String type, String id, String parentId, Object... fields) {
+ String name = type;
+ if (legacy() == false) {
+ type = "doc";
+ }
+
+ IndexRequestBuilder indexRequestBuilder = client().prepareIndex(index, type, id);
+ if (legacy()) {
+ if (parentId != null) {
+ indexRequestBuilder.setParent(parentId);
+ }
+ indexRequestBuilder.setSource(fields);
+ } else {
+ Map<String, Object> source = new HashMap<>();
+ for (int i = 0; i < fields.length; i += 2) {
+ source.put((String) fields[i], fields[i + 1]);
+ }
+ Map<String, Object> joinField = new HashMap<>();
+ if (parentId != null) {
+ joinField.put("name", name);
+ joinField.put("parent", parentId);
+ indexRequestBuilder.setRouting(parentId);
+ } else {
+ joinField.put("name", name);
+ }
+ source.put("join_field", joinField);
+ indexRequestBuilder.setSource(source);
+ }
+ indexRequestBuilder.setCreate(true);
+ return indexRequestBuilder;
+ }
+
@Before
public void setupCluster() throws Exception {
categoryToControl.clear();
- assertAcked(
+ if (legacy()) {
+ assertAcked(
prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
.addMapping("article", "category", "type=keyword")
.addMapping("comment", "_parent", "type=article", "commenter", "type=keyword")
- );
+ );
+ } else {
+ assertAcked(
+ prepareCreate("test")
+ .addMapping("doc", "category", "type=keyword", "join_field", "type=join,article=comment",
+ "commenter", "type=keyword")
+ );
+ }
List<IndexRequestBuilder> requests = new ArrayList<>();
String[] uniqueCategories = new String[randomIntBetween(1, 25)];
@@ -103,7 +145,7 @@ public class ChildrenIT extends ESIntegTestCase {
int numParentDocs = randomIntBetween(uniqueCategories.length, uniqueCategories.length * 5);
for (int i = 0; i < numParentDocs; i++) {
- String id = Integer.toString(i);
+ String id = "article-" + i;
// TODO: this array is always of length 1, and testChildrenAggs fails if this is changed
String[] categories = new String[randomIntBetween(1,1)];
@@ -116,8 +158,7 @@ public class ChildrenIT extends ESIntegTestCase {
control.articleIds.add(id);
}
- requests.add(client()
- .prepareIndex("test", "article", id).setCreate(true).setSource("category", categories, "randomized", true));
+ requests.add(createIndexRequest("test", "article", id, null, "category", categories, "randomized", true));
}
String[] commenters = new String[randomIntBetween(5, 50)];
@@ -131,31 +172,24 @@ public class ChildrenIT extends ESIntegTestCase {
int numChildDocsPerParent = randomIntBetween(0, 5);
for (int i = 0; i < numChildDocsPerParent; i++) {
String commenter = commenters[id % commenters.length];
- String idValue = Integer.toString(id++);
+ String idValue = "comment-" + id++;
control.commentIds.add(idValue);
Set<String> ids = control.commenterToCommentId.get(commenter);
if (ids == null) {
control.commenterToCommentId.put(commenter, ids = new HashSet<>());
}
ids.add(idValue);
- requests.add(client().prepareIndex("test", "comment", idValue)
- .setCreate(true).setParent(articleId).setSource("commenter", commenter));
+ requests.add(createIndexRequest("test", "comment", idValue, articleId, "commenter", commenter));
}
}
}
- requests.add(client().prepareIndex("test", "article", "a")
- .setSource("category", new String[]{"a"}, "randomized", false));
- requests.add(client().prepareIndex("test", "article", "b")
- .setSource("category", new String[]{"a", "b"}, "randomized", false));
- requests.add(client().prepareIndex("test", "article", "c")
- .setSource("category", new String[]{"a", "b", "c"}, "randomized", false));
- requests.add(client().prepareIndex("test", "article", "d")
- .setSource("category", new String[]{"c"}, "randomized", false));
- requests.add(client().prepareIndex("test", "comment", "a")
- .setParent("a").setSource("{}", XContentType.JSON));
- requests.add(client().prepareIndex("test", "comment", "c")
- .setParent("c").setSource("{}", XContentType.JSON));
+ requests.add(createIndexRequest("test", "article", "a", null, "category", new String[]{"a"}, "randomized", false));
+ requests.add(createIndexRequest("test", "article", "b", null, "category", new String[]{"a", "b"}, "randomized", false));
+ requests.add(createIndexRequest("test", "article", "c", null, "category", new String[]{"a", "b", "c"}, "randomized", false));
+ requests.add(createIndexRequest("test", "article", "d", null, "category", new String[]{"c"}, "randomized", false));
+ requests.add(createIndexRequest("test", "comment", "e", "a"));
+ requests.add(createIndexRequest("test", "comment", "f", "c"));
indexRandom(true, requests);
ensureSearchable("test");
@@ -184,11 +218,11 @@ public class ChildrenIT extends ESIntegTestCase {
Children childrenBucket = categoryBucket.getAggregations().get("to_comment");
assertThat(childrenBucket.getName(), equalTo("to_comment"));
assertThat(childrenBucket.getDocCount(), equalTo((long) entry1.getValue().commentIds.size()));
- assertThat((long) ((InternalAggregation)childrenBucket).getProperty("_count"),
+ assertThat(((InternalAggregation)childrenBucket).getProperty("_count"),
equalTo((long) entry1.getValue().commentIds.size()));
Terms commentersTerms = childrenBucket.getAggregations().get("commenters");
- assertThat((Terms) ((InternalAggregation)childrenBucket).getProperty("commenters"), sameInstance(commentersTerms));
+ assertThat(((InternalAggregation)childrenBucket).getProperty("commenters"), sameInstance(commentersTerms));
assertThat(commentersTerms.getBuckets().size(), equalTo(entry1.getValue().commenterToCommentId.size()));
for (Map.Entry<String, Set<String>> entry2 : entry1.getValue().commenterToCommentId.entrySet()) {
Terms.Bucket commentBucket = commentersTerms.getBucketByKey(entry2.getKey());
@@ -235,10 +269,8 @@ public class ChildrenIT extends ESIntegTestCase {
assertThat(childrenBucket.getDocCount(), equalTo(2L));
TopHits topHits = childrenBucket.getAggregations().get("top_comments");
assertThat(topHits.getHits().getTotalHits(), equalTo(2L));
- assertThat(topHits.getHits().getAt(0).getId(), equalTo("a"));
- assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment"));
- assertThat(topHits.getHits().getAt(1).getId(), equalTo("c"));
- assertThat(topHits.getHits().getAt(1).getType(), equalTo("comment"));
+ assertThat(topHits.getHits().getAt(0).getId(), equalTo("e"));
+ assertThat(topHits.getHits().getAt(1).getId(), equalTo("f"));
categoryBucket = categoryTerms.getBucketByKey("b");
assertThat(categoryBucket.getKeyAsString(), equalTo("b"));
@@ -249,8 +281,7 @@ public class ChildrenIT extends ESIntegTestCase {
assertThat(childrenBucket.getDocCount(), equalTo(1L));
topHits = childrenBucket.getAggregations().get("top_comments");
assertThat(topHits.getHits().getTotalHits(), equalTo(1L));
- assertThat(topHits.getHits().getAt(0).getId(), equalTo("c"));
- assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment"));
+ assertThat(topHits.getHits().getAt(0).getId(), equalTo("f"));
categoryBucket = categoryTerms.getBucketByKey("c");
assertThat(categoryBucket.getKeyAsString(), equalTo("c"));
@@ -261,25 +292,30 @@ public class ChildrenIT extends ESIntegTestCase {
assertThat(childrenBucket.getDocCount(), equalTo(1L));
topHits = childrenBucket.getAggregations().get("top_comments");
assertThat(topHits.getHits().getTotalHits(), equalTo(1L));
- assertThat(topHits.getHits().getAt(0).getId(), equalTo("c"));
- assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment"));
+ assertThat(topHits.getHits().getAt(0).getId(), equalTo("f"));
}
public void testWithDeletes() throws Exception {
String indexName = "xyz";
- assertAcked(
- prepareCreate(indexName)
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent")
- .addMapping("child", "_parent", "type=parent", "count", "type=long")
- );
+ if (legacy()) {
+ assertAcked(
+ prepareCreate(indexName)
+ .addMapping("parent")
+ .addMapping("child", "_parent", "type=parent", "count", "type=long")
+ );
+ } else {
+ assertAcked(
+ prepareCreate(indexName)
+ .addMapping("doc", "join_field", "type=join,parent=child", "count", "type=long")
+ );
+ }
List<IndexRequestBuilder> requests = new ArrayList<>();
- requests.add(client().prepareIndex(indexName, "parent", "1").setSource("{}", XContentType.JSON));
- requests.add(client().prepareIndex(indexName, "child", "0").setParent("1").setSource("count", 1));
- requests.add(client().prepareIndex(indexName, "child", "1").setParent("1").setSource("count", 1));
- requests.add(client().prepareIndex(indexName, "child", "2").setParent("1").setSource("count", 1));
- requests.add(client().prepareIndex(indexName, "child", "3").setParent("1").setSource("count", 1));
+ requests.add(createIndexRequest(indexName, "parent", "1", null));
+ requests.add(createIndexRequest(indexName, "child", "2", "1", "count", 1));
+ requests.add(createIndexRequest(indexName, "child", "3", "1", "count", 1));
+ requests.add(createIndexRequest(indexName, "child", "4", "1", "count", 1));
+ requests.add(createIndexRequest(indexName, "child", "5", "1", "count", 1));
indexRandom(true, requests);
for (int i = 0; i < 10; i++) {
@@ -294,17 +330,26 @@ public class ChildrenIT extends ESIntegTestCase {
Sum count = children.getAggregations().get("counts");
assertThat(count.getValue(), equalTo(4.));
- String idToUpdate = Integer.toString(randomInt(3));
+ String idToUpdate = Integer.toString(2 + randomInt(3));
/*
* The whole point of this test is to test these things with deleted
* docs in the index so we turn off detect_noop to make sure that
* the updates cause that.
*/
- UpdateResponse updateResponse = client().prepareUpdate(indexName, "child", idToUpdate)
- .setParent("1")
- .setDoc(Requests.INDEX_CONTENT_TYPE, "count", 1)
- .setDetectNoop(false)
- .get();
+ UpdateResponse updateResponse;
+ if (legacy()) {
+ updateResponse = client().prepareUpdate(indexName, "child", idToUpdate)
+ .setParent("1")
+ .setDoc(Requests.INDEX_CONTENT_TYPE, "count", 1)
+ .setDetectNoop(false)
+ .get();
+ } else {
+ updateResponse = client().prepareUpdate(indexName, "doc", idToUpdate)
+ .setRouting("1")
+ .setDoc(Requests.INDEX_CONTENT_TYPE, "count", 1)
+ .setDetectNoop(false)
+ .get();
+ }
assertThat(updateResponse.getVersion(), greaterThan(1L));
refresh();
}
@@ -326,35 +371,47 @@ public class ChildrenIT extends ESIntegTestCase {
String indexName = "prodcatalog";
String masterType = "masterprod";
String childType = "variantsku";
- assertAcked(
- prepareCreate(indexName)
- .setSettings("index.mapping.single_type", false)
- .addMapping(masterType, "brand", "type=text", "name", "type=keyword", "material", "type=text")
- .addMapping(childType, "_parent", "type=masterprod", "color", "type=keyword", "size", "type=keyword")
- );
+ if (legacy()) {
+ assertAcked(
+ prepareCreate(indexName)
+ .setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
+ .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
+ .put("index.mapping.single_type", false))
+ .addMapping(masterType, "brand", "type=text", "name", "type=keyword", "material", "type=text")
+ .addMapping(childType, "_parent", "type=masterprod", "color", "type=keyword", "size", "type=keyword")
+ );
+ } else {
+ assertAcked(
+ prepareCreate(indexName)
+ .setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
+ .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0))
+ .addMapping("doc", "join_field", "type=join," + masterType + "=" + childType, "brand", "type=text",
+ "name", "type=keyword", "material", "type=text", "color", "type=keyword", "size", "type=keyword")
+ );
+ }
List<IndexRequestBuilder> requests = new ArrayList<>();
- requests.add(client().prepareIndex(indexName, masterType, "1")
- .setSource("brand", "Levis", "name", "Style 501", "material", "Denim"));
- requests.add(client().prepareIndex(indexName, childType, "0").setParent("1").setSource("color", "blue", "size", "32"));
- requests.add(client().prepareIndex(indexName, childType, "1").setParent("1").setSource("color", "blue", "size", "34"));
- requests.add(client().prepareIndex(indexName, childType, "2").setParent("1").setSource("color", "blue", "size", "36"));
- requests.add(client().prepareIndex(indexName, childType, "3").setParent("1").setSource("color", "black", "size", "38"));
- requests.add(client().prepareIndex(indexName, childType, "4").setParent("1").setSource("color", "black", "size", "40"));
- requests.add(client().prepareIndex(indexName, childType, "5").setParent("1").setSource("color", "gray", "size", "36"));
-
- requests.add(client().prepareIndex(indexName, masterType, "2")
- .setSource("brand", "Wrangler", "name", "Regular Cut", "material", "Leather"));
- requests.add(client().prepareIndex(indexName, childType, "6").setParent("2").setSource("color", "blue", "size", "32"));
- requests.add(client().prepareIndex(indexName, childType, "7").setParent("2").setSource("color", "blue", "size", "34"));
- requests.add(client().prepareIndex(indexName, childType, "8").setParent("2").setSource("color", "black", "size", "36"));
- requests.add(client().prepareIndex(indexName, childType, "9").setParent("2").setSource("color", "black", "size", "38"));
- requests.add(client().prepareIndex(indexName, childType, "10").setParent("2").setSource("color", "black", "size", "40"));
- requests.add(client().prepareIndex(indexName, childType, "11").setParent("2").setSource("color", "orange", "size", "36"));
- requests.add(client().prepareIndex(indexName, childType, "12").setParent("2").setSource("color", "green", "size", "44"));
+ requests.add(createIndexRequest(indexName, masterType, "1", null, "brand", "Levis", "name",
+ "Style 501", "material", "Denim"));
+ requests.add(createIndexRequest(indexName, childType, "3", "1", "color", "blue", "size", "32"));
+ requests.add(createIndexRequest(indexName, childType, "4", "1", "color", "blue", "size", "34"));
+ requests.add(createIndexRequest(indexName, childType, "5", "1", "color", "blue", "size", "36"));
+ requests.add(createIndexRequest(indexName, childType, "6", "1", "color", "black", "size", "38"));
+ requests.add(createIndexRequest(indexName, childType, "7", "1", "color", "black", "size", "40"));
+ requests.add(createIndexRequest(indexName, childType, "8", "1", "color", "gray", "size", "36"));
+
+ requests.add(createIndexRequest(indexName, masterType, "2", null, "brand", "Wrangler", "name",
+ "Regular Cut", "material", "Leather"));
+ requests.add(createIndexRequest(indexName, childType, "9", "2", "color", "blue", "size", "32"));
+ requests.add(createIndexRequest(indexName, childType, "10", "2", "color", "blue", "size", "34"));
+ requests.add(createIndexRequest(indexName, childType, "12", "2", "color", "black", "size", "36"));
+ requests.add(createIndexRequest(indexName, childType, "13", "2", "color", "black", "size", "38"));
+ requests.add(createIndexRequest(indexName, childType, "14", "2", "color", "black", "size", "40"));
+ requests.add(createIndexRequest(indexName, childType, "15", "2", "color", "orange", "size", "36"));
+ requests.add(createIndexRequest(indexName, childType, "16", "2", "color", "green", "size", "44"));
indexRandom(true, requests);
- SearchResponse response = client().prepareSearch(indexName).setTypes(masterType)
+ SearchResponse response = client().prepareSearch(indexName)
.setQuery(hasChildQuery(childType, termQuery("color", "orange"), ScoreMode.None))
.addAggregation(children("my-refinements", childType)
.subAggregation(terms("my-colors").field("color"))
@@ -388,21 +445,27 @@ public class ChildrenIT extends ESIntegTestCase {
String grandParentType = "continent";
String parentType = "country";
String childType = "city";
- assertAcked(
- prepareCreate(indexName)
- .setSettings(Settings.builder()
- .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
- .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
- )
- .setSettings("index.mapping.single_type", false)
- .addMapping(grandParentType, "name", "type=keyword")
- .addMapping(parentType, "_parent", "type=" + grandParentType)
- .addMapping(childType, "_parent", "type=" + parentType)
- );
-
- client().prepareIndex(indexName, grandParentType, "1").setSource("name", "europe").get();
- client().prepareIndex(indexName, parentType, "2").setParent("1").setSource("name", "belgium").get();
- client().prepareIndex(indexName, childType, "3").setParent("2").setRouting("1").setSource("name", "brussels").get();
+ if (legacy()) {
+ assertAcked(
+ prepareCreate(indexName)
+ .setSettings(Settings.builder()
+ .put("index.mapping.single_type", false)
+ ).addMapping(grandParentType, "name", "type=keyword")
+ .addMapping(parentType, "_parent", "type=" + grandParentType)
+ .addMapping(childType, "_parent", "type=" + parentType)
+
+ );
+ } else {
+ assertAcked(
+ prepareCreate(indexName)
+ .addMapping("doc", "join_field", "type=join," + grandParentType + "=" + parentType + "," +
+ parentType + "=" + childType, "name", "type=keyword")
+ );
+ }
+
+ createIndexRequest(indexName, grandParentType, "1", null, "name", "europe").get();
+ createIndexRequest(indexName, parentType, "2", "1", "name", "belgium").get();
+ createIndexRequest(indexName, childType, "3", "2", "name", "brussels").setRouting("1").get();
refresh();
SearchResponse response = client().prepareSearch(indexName)
@@ -435,32 +498,37 @@ public class ChildrenIT extends ESIntegTestCase {
// Before we only evaluated segments that yielded matches in 'towns' and 'parent_names' aggs, which caused
// us to miss to evaluate child docs in segments we didn't have parent matches for.
-
- assertAcked(
- prepareCreate("index")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parentType", "name", "type=keyword", "town", "type=keyword")
- .addMapping("childType", "_parent", "type=parentType", "name", "type=keyword", "age", "type=integer")
- );
+ if (legacy()) {
+ assertAcked(
+ prepareCreate("index")
+ .addMapping("parentType", "name", "type=keyword", "town", "type=keyword")
+ .addMapping("childType", "_parent", "type=parentType", "name", "type=keyword", "age", "type=integer")
+ );
+ } else {
+ assertAcked(
+ prepareCreate("index")
+ .addMapping("doc", "join_field", "type=join,parentType=childType", "name", "type=keyword",
+ "town", "type=keyword", "age", "type=integer")
+ );
+ }
List<IndexRequestBuilder> requests = new ArrayList<>();
- requests.add(client().prepareIndex("index", "parentType", "1").setSource("name", "Bob", "town", "Memphis"));
- requests.add(client().prepareIndex("index", "parentType", "2").setSource("name", "Alice", "town", "Chicago"));
- requests.add(client().prepareIndex("index", "parentType", "3").setSource("name", "Bill", "town", "Chicago"));
- requests.add(client().prepareIndex("index", "childType", "1").setSource("name", "Jill", "age", 5).setParent("1"));
- requests.add(client().prepareIndex("index", "childType", "2").setSource("name", "Joey", "age", 3).setParent("1"));
- requests.add(client().prepareIndex("index", "childType", "3").setSource("name", "John", "age", 2).setParent("2"));
- requests.add(client().prepareIndex("index", "childType", "4").setSource("name", "Betty", "age", 6).setParent("3"));
- requests.add(client().prepareIndex("index", "childType", "5").setSource("name", "Dan", "age", 1).setParent("3"));
+ requests.add(createIndexRequest("index", "parentType", "1", null, "name", "Bob", "town", "Memphis"));
+ requests.add(createIndexRequest("index", "parentType", "2", null, "name", "Alice", "town", "Chicago"));
+ requests.add(createIndexRequest("index", "parentType", "3", null, "name", "Bill", "town", "Chicago"));
+ requests.add(createIndexRequest("index", "childType", "4", "1", "name", "Jill", "age", 5));
+ requests.add(createIndexRequest("index", "childType", "5", "1", "name", "Joey", "age", 3));
+ requests.add(createIndexRequest("index", "childType", "6", "2", "name", "John", "age", 2));
+ requests.add(createIndexRequest("index", "childType", "7", "3", "name", "Betty", "age", 6));
+ requests.add(createIndexRequest("index", "childType", "8", "3", "name", "Dan", "age", 1));
indexRandom(true, requests);
SearchResponse response = client().prepareSearch("index")
.setSize(0)
.addAggregation(AggregationBuilders.terms("towns").field("town")
.subAggregation(AggregationBuilders.terms("parent_names").field("name")
-.subAggregation(children("child_docs", "childType"))
+ .subAggregation(children("child_docs", "childType"))
)
- )
- .get();
+ ).get();
Terms towns = response.getAggregations().get("towns");
assertThat(towns.getBuckets().size(), equalTo(2));
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/LegacyChildrenIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/LegacyChildrenIT.java
new file mode 100644
index 0000000000..b64905d2aa
--- /dev/null
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/LegacyChildrenIT.java
@@ -0,0 +1,41 @@
+/*
+ * 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.join.aggregations;
+
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
+import org.elasticsearch.test.ESIntegTestCase.Scope;
+
+@ClusterScope(scope = Scope.SUITE)
+public class LegacyChildrenIT extends ChildrenIT {
+
+ @Override
+ protected boolean legacy() {
+ return true;
+ }
+
+ @Override
+ public Settings indexSettings() {
+ Settings indexSettings = super.indexSettings();
+ return Settings.builder()
+ .put(indexSettings)
+ .put("index.mapping.single_type", false)
+ .build();
+ }
+}
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregatorTests.java b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregatorTests.java
index 301721806c..e60c1a58bc 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregatorTests.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregatorTests.java
@@ -39,23 +39,22 @@ import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.ContentPath;
-import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.NumberFieldMapper;
-import org.elasticsearch.index.mapper.ParentFieldMapper;
-import org.elasticsearch.index.mapper.TypeFieldMapper;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.mapper.UidFieldMapper;
import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.join.mapper.MetaJoinFieldMapper;
+import org.elasticsearch.join.mapper.ParentJoinFieldMapper;
import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
import org.elasticsearch.search.aggregations.metrics.min.MinAggregationBuilder;
-import org.mockito.Mockito;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -139,42 +138,41 @@ public class ParentToChildrenAggregatorTests extends AggregatorTestCase {
}
private static List<Field> createParentDocument(String id) {
- return Arrays.asList(new StringField(TypeFieldMapper.NAME, PARENT_TYPE, Field.Store.NO),
+ return Arrays.asList(
new StringField(UidFieldMapper.NAME, Uid.createUid(PARENT_TYPE, id), Field.Store.NO),
- createJoinField(PARENT_TYPE, id));
+ new StringField("join_field", PARENT_TYPE, Field.Store.NO),
+ createJoinField(PARENT_TYPE, id)
+ );
}
private static List<Field> createChildDocument(String childId, String parentId, int value) {
- return Arrays.asList(new StringField(TypeFieldMapper.NAME, CHILD_TYPE, Field.Store.NO),
+ return Arrays.asList(
new StringField(UidFieldMapper.NAME, Uid.createUid(CHILD_TYPE, childId), Field.Store.NO),
- new SortedNumericDocValuesField("number", value),
- createJoinField(PARENT_TYPE, parentId));
+ new StringField("join_field", CHILD_TYPE, Field.Store.NO),
+ createJoinField(PARENT_TYPE, parentId),
+ new SortedNumericDocValuesField("number", value)
+ );
}
private static SortedDocValuesField createJoinField(String parentType, String id) {
- return new SortedDocValuesField(ParentFieldMapper.joinField(parentType), new BytesRef(id));
+ return new SortedDocValuesField("join_field#" + parentType, new BytesRef(id));
}
@Override
protected MapperService mapperServiceMock() {
+ ParentJoinFieldMapper joinFieldMapper = createJoinFieldMapper();
MapperService mapperService = mock(MapperService.class);
- DocumentMapper childDocMapper = mock(DocumentMapper.class);
- DocumentMapper parentDocMapper = mock(DocumentMapper.class);
- ParentFieldMapper parentFieldMapper = createParentFieldMapper();
- when(childDocMapper.parentFieldMapper()).thenReturn(parentFieldMapper);
- when(parentDocMapper.parentFieldMapper()).thenReturn(parentFieldMapper);
- when(mapperService.documentMapper(CHILD_TYPE)).thenReturn(childDocMapper);
- when(mapperService.documentMapper(PARENT_TYPE)).thenReturn(parentDocMapper);
- when(mapperService.docMappers(false)).thenReturn(Arrays.asList(new DocumentMapper[] { childDocMapper, parentDocMapper }));
- when(parentDocMapper.typeFilter(Mockito.any())).thenReturn(new TypeFieldMapper.TypesQuery(new BytesRef(PARENT_TYPE)));
- when(childDocMapper.typeFilter(Mockito.any())).thenReturn(new TypeFieldMapper.TypesQuery(new BytesRef(CHILD_TYPE)));
+ MetaJoinFieldMapper.MetaJoinFieldType metaJoinFieldType = mock(MetaJoinFieldMapper.MetaJoinFieldType.class);
+ when(metaJoinFieldType.getMapper()).thenReturn(joinFieldMapper);
+ when(mapperService.fullName("_parent_join")).thenReturn(metaJoinFieldType);
return mapperService;
}
- private static ParentFieldMapper createParentFieldMapper() {
+ private static ParentJoinFieldMapper createJoinFieldMapper() {
Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
- return new ParentFieldMapper.Builder("parent_type")
- .type(PARENT_TYPE).build(new Mapper.BuilderContext(settings, new ContentPath(0)));
+ return new ParentJoinFieldMapper.Builder("join_field")
+ .addParent(PARENT_TYPE, Collections.singleton(CHILD_TYPE))
+ .build(new Mapper.BuilderContext(settings, new ContentPath(0)));
}
private void testCase(Query query, IndexSearcher indexSearcher, Consumer<InternalChildren> verify)
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/query/ChildQuerySearchIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/query/ChildQuerySearchIT.java
index 2c828bb3cc..a80b9a35c6 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/query/ChildQuerySearchIT.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/query/ChildQuerySearchIT.java
@@ -19,22 +19,20 @@
package org.elasticsearch.join.query;
import org.apache.lucene.search.join.ScoreMode;
-import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
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.action.support.WriteRequest.RefreshPolicy;
-import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.IdsQueryBuilder;
@@ -52,7 +50,6 @@ 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.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
@@ -80,16 +77,15 @@ import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
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.parentId;
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.termsQuery;
-import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
-import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.fieldValueFactorFunction;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.weightFactorFunction;
+import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
+import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
@@ -99,9 +95,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
@ClusterScope(scope = Scope.SUITE)
public class ChildQuerySearchIT extends ESIntegTestCase {
@@ -130,6 +124,51 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
.build();
}
+ protected boolean legacy() {
+ return false;
+ }
+
+ private IndexRequestBuilder createIndexRequest(String index, String type, String id, String parentId, Object... fields) {
+ Map<String, Object> source = new HashMap<>();
+ for (int i = 0; i < fields.length; i += 2) {
+ source.put((String) fields[i], fields[i + 1]);
+ }
+ return createIndexRequest(index, type, id, parentId, source);
+ }
+
+ private IndexRequestBuilder createIndexRequest(String index, String type, String id, String parentId,
+ XContentBuilder builder) throws IOException {
+ Map<String, Object> source = XContentHelper.convertToMap(JsonXContent.jsonXContent, builder.string(), false);
+ return createIndexRequest(index, type, id, parentId, source);
+ }
+
+ private IndexRequestBuilder createIndexRequest(String index, String type, String id, String parentId, Map<String, Object> source) {
+ String name = type;
+ if (legacy() == false) {
+ type = "doc";
+ }
+
+ IndexRequestBuilder indexRequestBuilder = client().prepareIndex(index, type, id);
+ if (legacy()) {
+ if (parentId != null) {
+ indexRequestBuilder.setParent(parentId);
+ }
+ indexRequestBuilder.setSource(source);
+ } else {
+ Map<String, Object> joinField = new HashMap<>();
+ if (parentId != null) {
+ joinField.put("name", name);
+ joinField.put("parent", parentId);
+ indexRequestBuilder.setRouting(parentId);
+ } else {
+ joinField.put("name", name);
+ }
+ source.put("join_field", joinField);
+ indexRequestBuilder.setSource(source);
+ }
+ return indexRequestBuilder;
+ }
+
public void testSelfReferentialIsForbidden() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
prepareCreate("test").addMapping("type", "_parent", "type=type").get());
@@ -137,17 +176,20 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testMultiLevelChild() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent")
- .addMapping("child", "_parent", "type=parent")
- .addMapping("grandchild", "_parent", "type=child"));
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent")
+ .addMapping("child", "_parent", "type=parent")
+ .addMapping("grandchild", "_parent", "type=child"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child,child=grandchild"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "c_value1").get();
+ createIndexRequest("test", "grandchild", "gc1", "c1", "gc_field", "gc_value1").setRouting("p1").get();
refresh();
SearchResponse searchResponse = client()
@@ -197,15 +239,19 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// see #2744
public void test2744() throws IOException {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("foo")
- .addMapping("test", "_parent", "type=foo"));
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
+ .addMapping("foo")
+ .addMapping("test", "_parent", "type=foo"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,foo=test"));
+ }
ensureGreen();
// index simple data
- client().prepareIndex("test", "foo", "1").setSource("foo", 1).get();
- client().prepareIndex("test", "test").setSource("foo", 1).setParent("1").get();
+ createIndexRequest("test", "foo", "1", null, "foo", 1).get();
+ createIndexRequest("test", "test", "2", "1", "foo", 1).get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").
setQuery(hasChildQuery("test", matchQuery("foo", 1), ScoreMode.None))
@@ -217,46 +263,78 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testSimpleChildQuery() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent")
- .addMapping("child", "_parent", "type=parent"));
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent")
+ .addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "red").get();
refresh();
// TEST FETCHING _parent from child
- SearchResponse searchResponse = client().prepareSearch("test")
- .setQuery(idsQuery("child").addIds("c1")).storedFields("_parent").execute()
- .actionGet();
- assertNoFailures(searchResponse);
- assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
- assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("c1"));
- assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue().toString(), equalTo("p1"));
+ SearchResponse searchResponse;
+ if (legacy()) {
+ searchResponse = client().prepareSearch("test")
+ .setQuery(idsQuery("child").addIds("c1")).storedFields("_parent").get();
+ assertNoFailures(searchResponse);
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
+ assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("c1"));
+ assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue(), equalTo("p1"));
+ } else {
+ searchResponse = client().prepareSearch("test")
+ .setQuery(idsQuery("doc").addIds("c1")).get();
+ assertNoFailures(searchResponse);
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
+ assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("c1"));
+ assertThat(searchResponse.getHits().getAt(0).field("join_field").getValue(), equalTo("child"));
+ assertThat(searchResponse.getHits().getAt(0).field("join_field#parent").getValue(), equalTo("p1"));
+ }
// TEST matching on parent
- searchResponse = client().prepareSearch("test").setQuery(termQuery("_parent#parent", "p1")).storedFields("_parent").get();
- assertNoFailures(searchResponse);
- assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
- assertThat(searchResponse.getHits().getAt(0).getId(), anyOf(equalTo("c1"), equalTo("c2")));
- assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue().toString(), equalTo("p1"));
- assertThat(searchResponse.getHits().getAt(1).getId(), anyOf(equalTo("c1"), equalTo("c2")));
- assertThat(searchResponse.getHits().getAt(1).field("_parent").getValue().toString(), equalTo("p1"));
+ if (legacy()) {
+ searchResponse = client().prepareSearch("test").setQuery(termQuery("_parent#parent", "p1")).storedFields("_parent").get();
+ assertNoFailures(searchResponse);
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+ assertThat(searchResponse.getHits().getAt(0).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue(), equalTo("p1"));
+ assertThat(searchResponse.getHits().getAt(1).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(1).field("_parent").getValue(), equalTo("p1"));
+ } else {
+ searchResponse = client().prepareSearch("test")
+ .setQuery(boolQuery().filter(termQuery("join_field#parent", "p1")).filter(termQuery("join_field", "child")))
+ .get();
+ assertNoFailures(searchResponse);
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+ assertThat(searchResponse.getHits().getAt(0).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(0).field("join_field").getValue(), equalTo("child"));
+ assertThat(searchResponse.getHits().getAt(0).field("join_field#parent").getValue(), equalTo("p1"));
+ assertThat(searchResponse.getHits().getAt(1).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(1).field("join_field").getValue(), equalTo("child"));
+ assertThat(searchResponse.getHits().getAt(1).field("join_field#parent").getValue(), equalTo("p1"));
+ }
- searchResponse = client().prepareSearch("test").setQuery(queryStringQuery("_parent#parent:p1")).storedFields("_parent").get();
- assertNoFailures(searchResponse);
- assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
- assertThat(searchResponse.getHits().getAt(0).getId(), anyOf(equalTo("c1"), equalTo("c2")));
- assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue().toString(), equalTo("p1"));
- assertThat(searchResponse.getHits().getAt(1).getId(), anyOf(equalTo("c1"), equalTo("c2")));
- assertThat(searchResponse.getHits().getAt(1).field("_parent").getValue().toString(), equalTo("p1"));
+ if (legacy()) {
+ searchResponse = client().prepareSearch("test").setQuery(queryStringQuery("_parent#parent:p1")).storedFields("_parent").get();
+ assertNoFailures(searchResponse);
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+ assertThat(searchResponse.getHits().getAt(0).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(0).field("_parent").getValue(), equalTo("p1"));
+ assertThat(searchResponse.getHits().getAt(1).getId(), anyOf(equalTo("c1"), equalTo("c2")));
+ assertThat(searchResponse.getHits().getAt(1).field("_parent").getValue(), equalTo("p1"));
+ } else {
+ // doesn't make sense for join field, because query string & term query om this field have no special logic.
+ }
// HAS CHILD
searchResponse = client().prepareSearch("test").setQuery(randomHasChild("child", "c_field", "yellow"))
@@ -292,25 +370,28 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// Issue #3290
public void testCachingBugWithFqueryFilter() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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));
+ builders.add(createIndexRequest("test", "parent", Integer.toString(i), null, "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));
+ builders.add(createIndexRequest("test", "child", j + "-" + i, "0", "c_field", i));
}
- 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)));
+ for (int i = 10; i < 20; i++) {
+ builders.add(createIndexRequest("test", "child", j + "-" + i, Integer.toString(i), "c_field", i));
}
if (randomBoolean()) {
@@ -333,14 +414,18 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testHasParentFilter() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
Map<String, Set<String>> parentToChildren = new HashMap<>();
// Childless parent
- client().prepareIndex("test", "parent", "p0").setSource("p_field", "p0").get();
+ createIndexRequest("test", "parent", "p0", null, "p_field", "p0").get();
parentToChildren.put("p0", new HashSet<>());
String previousParentId = null;
@@ -351,12 +436,12 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
if (previousParentId == null || i % numChildDocsPerParent == 0) {
previousParentId = "p" + i;
- builders.add(client().prepareIndex("test", "parent", previousParentId).setSource("p_field", previousParentId));
+ builders.add(createIndexRequest("test", "parent", previousParentId, null, "p_field", previousParentId));
numChildDocsPerParent++;
}
String childId = "c" + i;
- builders.add(client().prepareIndex("test", "child", childId).setSource("c_field", childId).setParent(previousParentId));
+ builders.add(createIndexRequest("test", "child", childId, previousParentId, "c_field", childId));
if (!parentToChildren.containsKey(previousParentId)) {
parentToChildren.put(previousParentId, new HashSet<>());
@@ -383,24 +468,28 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testSimpleChildQueryWithFlush() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
// index simple data with flushes, so we have many segments
- client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
client().admin().indices().prepareFlush().get();
- client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
client().admin().indices().prepareFlush().get();
- client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
client().admin().indices().prepareFlush().get();
- client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
client().admin().indices().prepareFlush().get();
- client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "blue").get();
client().admin().indices().prepareFlush().get();
- client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "red").get();
client().admin().indices().prepareFlush().get();
refresh();
@@ -453,19 +542,23 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testScopedFacet() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent", "c_field", "type=keyword"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child", "c_field", "type=keyword"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "red").get();
refresh();
@@ -493,18 +586,22 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testDeletedParent() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "red").get();
refresh();
@@ -517,7 +614,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// update p1 and see what that we get updated values...
- client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1_updated").get();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1_updated").get();
client().admin().indices().prepareRefresh().get();
searchResponse = client().prepareSearch("test")
@@ -529,19 +626,23 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testDfsSearchType() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p3", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "red").get();
refresh();
@@ -558,17 +659,21 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testHasChildAndHasParentFailWhenSomeSegmentsDontContainAnyParentOrChildDocs() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
- client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
- client().prepareIndex("test", "child", "1").setParent("1").setSource("c_field", 1).get();
+ createIndexRequest("test", "parent", "1", null, "p_field", 1).get();
+ createIndexRequest("test", "child", "2", "1", "c_field", 1).get();
client().admin().indices().prepareFlush("test").get();
- client().prepareIndex("test", "type1", "1").setSource("p_field", 1).get();
+ client().prepareIndex("test", legacy() ? "type1" : "doc", "3").setSource("p_field", 1).get();
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test")
@@ -583,15 +688,19 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testCountApiUsage() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", parentId, null, "p_field", "1").get();
+ createIndexRequest("test", "child", "c1", parentId, "c_field", "1").get();
refresh();
SearchResponse countResponse = client().prepareSearch("test").setSize(0)
@@ -616,15 +725,19 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testExplainUsage() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", parentId, null, "p_field", "1").get();
+ createIndexRequest("test", "child", "c1", parentId, "c_field", "1").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
@@ -641,75 +754,62 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertHitCount(searchResponse, 1L);
assertThat(searchResponse.getHits().getAt(0).getExplanation().getDescription(), containsString("join value p1"));
- ExplainResponse explainResponse = client().prepareExplain("test", "parent", parentId)
+ ExplainResponse explainResponse = client().prepareExplain("test", legacy() ? "parent" : "doc", parentId)
.setQuery(hasChildQuery("child", termQuery("c_field", "1"), ScoreMode.Max))
.get();
assertThat(explainResponse.isExists(), equalTo(true));
- assertThat(explainResponse.getExplanation().getDetails()[0].getDescription(), containsString("join value p1"));
+ assertThat(explainResponse.getExplanation().toString(), containsString("join value p1"));
}
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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "1", null, "p_field", "p_value1"));
+ indexBuilders.add(createIndexRequest("test", "child", "4", "1", "c_field1", 1, "c_field2", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "5", "1", "c_field1", 1, "c_field2", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "6", "1", "c_field1", 2, "c_field2", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "7", "1", "c_field1", 2, "c_field2", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "8", "1", "c_field1", 1, "c_field2", 1));
+ indexBuilders.add(createIndexRequest("test", "child", "9", "1", "c_field1", 1, "c_field2", 2));
// 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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "2", null, "p_field", "p_value2"));
+ indexBuilders.add(createIndexRequest("test", "child", "10", "2", "c_field1", 3, "c_field2", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "11", "2", "c_field1", 1, "c_field2", 1));
+ indexBuilders.add(createIndexRequest("test", "child", "12", "p", "c_field1", 1, "c_field2", 1)); // why "p"????
+ indexBuilders.add(createIndexRequest("test", "child", "13", "2", "c_field1", 1, "c_field2", 1));
+ indexBuilders.add(createIndexRequest("test", "child", "14", "2", "c_field1", 1, "c_field2", 1));
+ indexBuilders.add(createIndexRequest("test", "child", "15", "2", "c_field1", 1, "c_field2", 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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "3", null, "p_field1", "p_value3", "p_field2", 5));
+ indexBuilders.add(createIndexRequest("test", "child", "16", "3", "c_field1", 4, "c_field2", 0, "c_field3", 0));
+ indexBuilders.add(createIndexRequest("test", "child", "17", "3", "c_field1", 1, "c_field2", 1, "c_field3", 1));
+ indexBuilders.add(createIndexRequest("test", "child", "18", "3", "c_field1", 1, "c_field2", 2, "c_field3", 2));
+ indexBuilders.add(createIndexRequest("test", "child", "19", "3", "c_field1", 1, "c_field2", 2, "c_field3", 3));
+ indexBuilders.add(createIndexRequest("test", "child", "20", "3", "c_field1", 1, "c_field2", 2, "c_field3", 4));
+ indexBuilders.add(createIndexRequest("test", "child", "21", "3", "c_field1", 1, "c_field2", 2, "c_field3", 5));
+ indexBuilders.add(createIndexRequest("test", "child1", "22", "3", "c_field1", 1, "c_field2", 2, "c_field3", 6));
return indexBuilders;
}
public void testScoreForParentChildQueriesWithFunctionScore() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent")
.addMapping("child1", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", jsonBuilder().startObject().startObject("doc").startObject("properties")
+ .startObject("join_field")
+ .field("type", "join")
+ .field("parent", new String[] {"child", "child1"})
+ .endObject()
+ .endObject().endObject().endObject()
+ ));
+ }
ensureGreen();
indexRandom(true, createDocBuilders().toArray(new IndexRequestBuilder[0]));
@@ -775,28 +875,32 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
.addSort(SortBuilders.fieldSort("c_field3")).addSort(SortBuilders.scoreSort()).get();
assertThat(response.getHits().getTotalHits(), equalTo(7L));
- assertThat(response.getHits().getHits()[0].getId(), equalTo("13"));
+ assertThat(response.getHits().getHits()[0].getId(), equalTo("16"));
assertThat(response.getHits().getHits()[0].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[1].getId(), equalTo("14"));
+ assertThat(response.getHits().getHits()[1].getId(), equalTo("17"));
assertThat(response.getHits().getHits()[1].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[2].getId(), equalTo("15"));
+ assertThat(response.getHits().getHits()[2].getId(), equalTo("18"));
assertThat(response.getHits().getHits()[2].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[3].getId(), equalTo("16"));
+ assertThat(response.getHits().getHits()[3].getId(), equalTo("19"));
assertThat(response.getHits().getHits()[3].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[4].getId(), equalTo("17"));
+ assertThat(response.getHits().getHits()[4].getId(), equalTo("20"));
assertThat(response.getHits().getHits()[4].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[5].getId(), equalTo("18"));
+ assertThat(response.getHits().getHits()[5].getId(), equalTo("21"));
assertThat(response.getHits().getHits()[5].getScore(), equalTo(5f));
- assertThat(response.getHits().getHits()[6].getId(), equalTo("1"));
+ assertThat(response.getHits().getHits()[6].getId(), equalTo("22"));
assertThat(response.getHits().getHits()[6].getScore(), equalTo(5f));
}
// Issue #2536
public void testParentChildQueriesCanHandleNoRelevantTypesInIndex() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
SearchResponse response = client().prepareSearch("test")
@@ -804,8 +908,13 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertNoFailures(response);
assertThat(response.getHits().getTotalHits(), equalTo(0L));
- client().prepareIndex("test", "child1").setSource(jsonBuilder().startObject().field("text", "value").endObject())
+ if (legacy()) {
+ client().prepareIndex("test", "child1").setSource(jsonBuilder().startObject().field("text", "value").endObject())
+ .setRefreshPolicy(RefreshPolicy.IMMEDIATE).get();
+ } else {
+ client().prepareIndex("test", "doc").setSource(jsonBuilder().startObject().field("text", "value").endObject())
.setRefreshPolicy(RefreshPolicy.IMMEDIATE).get();
+ }
response = client().prepareSearch("test")
.setQuery(hasChildQuery("child", matchQuery("text", "value"), ScoreMode.None)).get();
@@ -829,17 +938,25 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testHasChildAndHasParentFilter_withFilter() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
- client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
- client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get();
+ createIndexRequest("test", "parent", "1", null, "p_field", 1).get();
+ createIndexRequest("test", "child", "2", "1", "c_field", 1).get();
client().admin().indices().prepareFlush("test").get();
- client().prepareIndex("test", "type1", "3").setSource("p_field", 2).get();
+ if (legacy()) {
+ client().prepareIndex("test", "type1", "3").setSource("p_field", 2).get();
+ } else {
+ client().prepareIndex("test", "doc", "3").setSource("p_field", 2).get();
+ }
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test")
@@ -857,15 +974,20 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("2"));
}
+ @AwaitsFix(bugUrl = "wait for inner hits to be fixed")
public void testHasChildInnerHitsHighlighting() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
- client().prepareIndex("test", "parent", "1").setSource("p_field", 1).get();
- client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", "foo bar").get();
+ createIndexRequest("test", "parent", "1", null, "p_field", 1).get();
+ createIndexRequest("test", "child", "2", "1", "c_field", "foo bar").get();
client().admin().indices().prepareFlush("test").get();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(
@@ -884,16 +1006,20 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testHasChildAndHasParentWrappedInAQueryFilter() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "1", null, "p_field", 1).get();
client().admin().indices().prepareFlush("test").setForce(true).get();
- client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get();
+ createIndexRequest("test", "child", "2", "1", "c_field", 1).get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
@@ -918,21 +1044,25 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testSimpleQueryRewrite() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent", "p_field", "type=keyword")
.addMapping("child", "_parent", "type=parent", "c_field", "type=keyword"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child", "p_field", "type=keyword", "c_field", "type=keyword"));
+ }
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();
+ createIndexRequest("test", "parent", parentId, null, "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();
+ createIndexRequest("test", "child", childUid, parentId, "c_field", childUid).get();
}
childId = j;
}
@@ -967,19 +1097,23 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// Issue #3144
public void testReIndexingParentAndChildDocuments() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "yellow").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "x").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "x").get();
refresh();
@@ -1002,10 +1136,10 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// 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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "d" + i, "p1", "c_field", "red").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "x").get();
client().admin().indices().prepareRefresh("test").get();
}
@@ -1030,19 +1164,23 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
// Issue #3203
public void testHasChildQueryWithMinimumScore() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "x").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "x").get();
+ createIndexRequest("test", "child", "c4", "p2", "c_field", "x").get();
+ createIndexRequest("test", "child", "c5", "p2", "c_field", "x").get();
refresh();
SearchResponse searchResponse = client()
@@ -1056,41 +1194,84 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testParentFieldQuery() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.refresh_interval", -1, "index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
+ .setSettings(Settings.builder()
+ .put(indexSettings())
+ .put("index.refresh_interval", -1)
+ )
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .setSettings("index.refresh_interval", -1)
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
- SearchResponse response = client().prepareSearch("test").setQuery(termQuery("_parent", "p1"))
+ SearchResponse response;
+ if (legacy()){
+ response = client().prepareSearch("test").setQuery(termQuery("_parent#parent:p1", "p1"))
+ .get();
+ } else {
+ response = client().prepareSearch("test")
+ .setQuery(boolQuery().filter(termQuery("join_field#parent", "p1")).filter(termQuery("join_field", "child")))
.get();
+ }
assertHitCount(response, 0L);
- client().prepareIndex("test", "child", "c1").setSource("{}", XContentType.JSON).setParent("p1").get();
+ createIndexRequest("test", "child", "c1", "p1").get();
refresh();
- response = client().prepareSearch("test").setQuery(termQuery("_parent#parent", "p1")).get();
+ if (legacy()){
+ response = client().prepareSearch("test").setQuery(termQuery("_parent#parent", "p1"))
+ .get();
+ } else {
+ response = client().prepareSearch("test")
+ .setQuery(boolQuery().filter(termQuery("join_field#parent", "p1")).filter(termQuery("join_field", "child")))
+ .get();
+ }
assertHitCount(response, 1L);
- response = client().prepareSearch("test").setQuery(queryStringQuery("_parent#parent:p1")).get();
- assertHitCount(response, 1L);
+ if (legacy()) {
+ response = client().prepareSearch("test").setQuery(queryStringQuery("_parent#parent:p1")).get();
+ assertHitCount(response, 1L);
+ }
- client().prepareIndex("test", "child", "c2").setSource("{}", XContentType.JSON).setParent("p2").get();
+ createIndexRequest("test", "child", "c2", "p2").get();
refresh();
- response = client().prepareSearch("test").setQuery(termsQuery("_parent#parent", "p1", "p2")).get();
- assertHitCount(response, 2L);
+ if (legacy()) {
+ response = client().prepareSearch("test").setQuery(termsQuery("_parent#parent", "p1", "p2")).get();
+ assertHitCount(response, 2L);
+ }
- response = client().prepareSearch("test")
+ if (legacy()) {
+ response = client().prepareSearch("test")
.setQuery(boolQuery()
.should(termQuery("_parent#parent", "p1"))
.should(termQuery("_parent#parent", "p2"))
).get();
+ } else {
+ response = client().prepareSearch("test")
+ .setQuery(boolQuery()
+ .should(boolQuery().filter(termQuery("join_field#parent", "p1")).filter(termQuery("join_field", "child")))
+ .should(boolQuery().filter(termQuery("join_field#parent", "p2")).filter(termQuery("join_field", "child")))
+ ).get();
+ }
assertHitCount(response, 2L);
}
public void testParentIdQuery() throws Exception {
+ if (legacy() == false) {
+ // Fix parent_id query
+ return;
+ }
+
assertAcked(prepareCreate("test")
- .setSettings("index.refresh_interval", -1, "index.mapping.single_type", false)
+ .setSettings(Settings.builder()
+ .put(indexSettings())
+ .put("index.refresh_interval", -1)
+ )
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
ensureGreen();
@@ -1113,24 +1294,28 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testHasChildNotBeingCached() throws IOException {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "parent", "p3", null, "p_field", "p_value3").get();
+ createIndexRequest("test", "parent", "p4", null, "p_field", "p_value4").get();
+ createIndexRequest("test", "parent", "p5", null, "p_field", "p_value5").get();
+ createIndexRequest("test", "parent", "p6", null, "p_field", "p_value6").get();
+ createIndexRequest("test", "parent", "p7", null, "p_field", "p_value7").get();
+ createIndexRequest("test", "parent", "p8", null, "p_field", "p_value8").get();
+ createIndexRequest("test", "parent", "p9", null, "p_field", "p_value9").get();
+ createIndexRequest("test", "parent", "p10", null, "p_field", "p_value10").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "blue").get();
client().admin().indices().prepareFlush("test").get();
client().admin().indices().prepareRefresh("test").get();
@@ -1140,7 +1325,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
- client().prepareIndex("test", "child", "c2").setParent("p2").setSource("c_field", "blue").get();
+ createIndexRequest("test", "child", "c2", "p2", "c_field", "blue").get();
client().admin().indices().prepareRefresh("test").get();
searchResponse = client().prepareSearch("test")
@@ -1175,22 +1360,29 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
// Issue #3818
- public void testHasChildQueryOnlyReturnsSingleChildType() {
- assertAcked(prepareCreate("grandissue")
- .setSettings("index.mapping.single_type", false)
+ public void testHasChildQueryOnlyReturnsSingleChildType() throws Exception {
+ if (legacy()) {
+ assertAcked(prepareCreate("grandissue")
.addMapping("grandparent", "name", "type=text")
.addMapping("parent", "_parent", "type=grandparent")
.addMapping("child_type_one", "_parent", "type=parent")
.addMapping("child_type_two", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("grandissue")
+ .addMapping("doc", jsonBuilder().startObject().startObject("doc").startObject("properties")
+ .startObject("join_field")
+ .field("type", "join")
+ .field("grandparent", "parent")
+ .field("parent", new String[] {"child_type_one", "child_type_two"})
+ .endObject()
+ .endObject().endObject().endObject()
+ ));
+ }
- 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();
+ createIndexRequest("grandissue", "grandparent", "1", null, "name", "Grandpa").get();
+ createIndexRequest("grandissue", "parent", "2", "1", "name", "Dana").get();
+ createIndexRequest("grandissue", "child_type_one", "3", "2", "name", "William").setRouting("1").get();
+ createIndexRequest("grandissue", "child_type_two", "4", "2", "name", "Kate").setRouting("1").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("grandissue").setQuery(
@@ -1228,64 +1420,18 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertHitCount(searchResponse, 0L);
}
- public void testIndexChildDocWithNoParentMapping() throws IOException {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent")
- .addMapping("child1"));
- ensureGreen();
-
- client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
- try {
- client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get();
- fail();
- } catch (IllegalArgumentException 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 (IllegalArgumentException e) {
- assertThat(e.toString(), containsString("can't specify parent if no parent field has been configured"));
- }
-
- refresh();
- }
-
- public void testAddingParentToExistingMapping() throws 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 (IllegalArgumentException e) {
- assertThat(e.toString(), containsString("The _parent field's type option can't be changed: [null]->[parent]"));
- }
- }
-
public void testHasChildQueryWithNestedInnerObjects() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent", "objects", "type=nested")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child", "objects", "type=nested"));
+ }
ensureGreen();
- client().prepareIndex("test", "parent", "p1")
- .setSource(jsonBuilder().startObject().field("p_field", "1").startArray("objects")
+ createIndexRequest("test", "parent", "p1", null, 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()
@@ -1294,15 +1440,14 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
.startObject().field("i_field", "6").endObject()
.endArray().endObject())
.get();
- client().prepareIndex("test", "parent", "p2")
- .setSource(jsonBuilder().startObject().field("p_field", "2").startArray("objects")
+ createIndexRequest("test", "parent", "p2", null, 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();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "red").get();
refresh();
ScoreMode scoreMode = randomFrom(ScoreMode.values());
@@ -1322,15 +1467,19 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testNamedFilters() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", parentId, null, "p_field", "1").get();
+ createIndexRequest("test", "child", "c1", parentId, "c_field", "1").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child",
@@ -1370,7 +1519,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
ensureGreen();
String parentId = "p1";
- client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").get();
+ client().prepareIndex("test", legacy() ? "parent" : "doc", parentId).setSource("p_field", "1").get();
refresh();
try {
@@ -1420,24 +1569,33 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testParentChildCaching() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.refresh_interval", -1, "index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
+ .setSettings(Settings.builder()
+ .put(indexSettings())
+ .put("index.refresh_interval", -1)
+ )
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .setSettings("index.refresh_interval", -1)
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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();
+ createIndexRequest("test", "parent", "p1", null, "p_field", "p_value1").get();
+ createIndexRequest("test", "parent", "p2", null, "p_field", "p_value2").get();
+ createIndexRequest("test", "child", "c1", "p1", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c2", "p1", "c_field", "red").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "red").get();
client().admin().indices().prepareForceMerge("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();
+ createIndexRequest("test", "parent", "p3", null, "p_field", "p_value3").get();
+ createIndexRequest("test", "parent", "p4", null, "p_field", "p_value4").get();
+ createIndexRequest("test", "child", "c4", "p3", "c_field", "green").get();
+ createIndexRequest("test", "child", "c5", "p3", "c_field", "blue").get();
+ createIndexRequest("test", "child", "c6", "p4", "c_field", "blue").get();
client().admin().indices().prepareFlush("test").get();
client().admin().indices().prepareRefresh("test").get();
@@ -1451,7 +1609,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
- client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "blue").get();
+ createIndexRequest("test", "child", "c3", "p2", "c_field", "blue").get();
client().admin().indices().prepareRefresh("test").get();
SearchResponse searchResponse = client().prepareSearch()
@@ -1464,14 +1622,18 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testParentChildQueriesViaScrollApi() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
for (int i = 0; i < 10; i++) {
- client().prepareIndex("test", "parent", "p" + i).setSource("{}", XContentType.JSON).get();
- client().prepareIndex("test", "child", "c" + i).setSource("{}", XContentType.JSON).setParent("p" + i).get();
+ createIndexRequest("test", "parent", "p" + i, null).get();
+ createIndexRequest("test", "child", "c" + i, "p" + i).get();
}
refresh();
@@ -1507,58 +1669,21 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
}
- // Issue #5783
- public void testQueryBeforeChildType() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .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(new SearchSourceBuilder().query(hasChildQuery("posts",
- QueryBuilders.matchQuery("field", "bar"), ScoreMode.None)))
- .get();
- assertHitCount(resp, 1L);
- }
-
- // Issue #6256
- public void testParentFieldInMultiMatchField() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .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#type1"))
- .get();
-
- assertThat(response.getHits().getTotalHits(), equalTo(1L));
- assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
- }
-
public void testTypeIsAppliedInHasParentInnerQuery() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
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("{}", XContentType.JSON));
- indexRequests.add(client().prepareIndex("test", "child", "2").setParent("1").setSource("{}", XContentType.JSON));
+ indexRequests.add(createIndexRequest("test", "parent", "p1", null, "field1", "a"));
+ indexRequests.add(createIndexRequest("test", "child", "c1", "p1"));
+ indexRequests.add(createIndexRequest("test", "child", "c2", "p1"));
indexRandom(true, indexRequests);
SearchResponse searchResponse = client().prepareSearch("test")
@@ -1585,36 +1710,26 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "1", null, "id",1));
+ indexBuilders.add(createIndexRequest("test", "child", "10", "1", "foo", "one"));
// 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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "2", null, "id",2));
+ indexBuilders.add(createIndexRequest("test", "child", "11", "2", "foo", "one"));
+ indexBuilders.add(createIndexRequest("test", "child", "12", "2", "foo", "one two"));
// 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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "3", null, "id",3));
+ indexBuilders.add(createIndexRequest("test", "child", "13", "3", "foo", "one"));
+ indexBuilders.add(createIndexRequest("test", "child", "14", "3", "foo", "one two"));
+ indexBuilders.add(createIndexRequest("test", "child", "15", "3", "foo", "one two three"));
// 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"));
+ indexBuilders.add(createIndexRequest("test", "parent", "4", null, "id", 4));
+ indexBuilders.add(createIndexRequest("test", "child", "16", "4", "foo", "one"));
+ indexBuilders.add(createIndexRequest("test", "child", "17", "4", "foo", "one two"));
+ indexBuilders.add(createIndexRequest("test", "child", "18", "4", "foo", "one two three"));
+ indexBuilders.add(createIndexRequest("test", "child", "19", "4", "foo", "one two three four"));
return indexBuilders;
}
@@ -1639,10 +1754,14 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testMinMaxChildren() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent", "id", "type=long")
.addMapping("child", "_parent", "type=parent"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent=child"));
+ }
ensureGreen();
indexRandom(true, createMinMaxDocBuilders().toArray(new IndexRequestBuilder[0]));
@@ -1953,59 +2072,41 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertThat(e.getMessage(), equalTo("[has_child] 'max_children' is less than 'min_children'"));
}
- public void testParentFieldToNonExistingType() {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent").addMapping("child", "_parent", "type=parent2"));
- client().prepareIndex("test", "parent", "1").setSource("{}", XContentType.JSON).get();
- client().prepareIndex("test", "child", "1").setParent("1").setSource("{}", XContentType.JSON).get();
- refresh();
-
- try {
- client().prepareSearch("test")
- .setQuery(hasChildQuery("child", matchAllQuery(), ScoreMode.None))
- .get();
- fail();
- } catch (SearchPhaseExecutionException e) {
- }
- }
-
public void testHasParentInnerQueryType() {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent-type").addMapping("child-type", "_parent", "type=parent-type"));
- client().prepareIndex("test", "child-type", "child-id").setParent("parent-id").setSource("{}", XContentType.JSON).get();
- client().prepareIndex("test", "parent-type", "parent-id").setSource("{}", XContentType.JSON).get();
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent-type=child-type"));
+ }
+ createIndexRequest("test", "child-type", "child-id", "parent-id").get();
+ createIndexRequest("test", "parent-type", "parent-id", null).get();
refresh();
- //make sure that when we explicitly set a type, the inner query is executed in the context of the parent type instead
- SearchResponse searchResponse = client().prepareSearch("test").setTypes("child-type").setQuery(
- hasParentQuery("parent-type", new IdsQueryBuilder().addIds("parent-id"), false)).get();
- assertSearchHits(searchResponse, "child-id");
- }
- public void testHasChildInnerQueryType() {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent-type").addMapping("child-type", "_parent", "type=parent-type"));
- client().prepareIndex("test", "child-type", "child-id").setParent("parent-id").setSource("{}", XContentType.JSON).get();
- client().prepareIndex("test", "parent-type", "parent-id").setSource("{}", XContentType.JSON).get();
- refresh();
//make sure that when we explicitly set a type, the inner query is executed in the context of the child type instead
- SearchResponse searchResponse = client().prepareSearch("test").setTypes("parent-type").setQuery(
- hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"), ScoreMode.None)).get();
+ SearchResponse searchResponse = client().prepareSearch("test").setQuery(
+ hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"), ScoreMode.None)).get();
assertSearchHits(searchResponse, "parent-id");
+ //make sure that when we explicitly set a type, the inner query is executed in the context of the parent type instead
+ searchResponse = client().prepareSearch("test").setQuery(
+ hasParentQuery("parent-type", new IdsQueryBuilder().addIds("parent-id"), false)).get();
+ assertSearchHits(searchResponse, "child-id");
}
public void testHighlightersIgnoreParentChild() {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
+ if (legacy()) {
+ assertAcked(prepareCreate("test")
.addMapping("parent-type", "searchText", "type=text,term_vector=with_positions_offsets,index_options=offsets")
.addMapping("child-type", "_parent", "type=parent-type", "searchText",
- "type=text,term_vector=with_positions_offsets,index_options=offsets"));
- client().prepareIndex("test", "parent-type", "parent-id")
- .setSource("searchText", "quick brown fox").get();
- client().prepareIndex("test", "child-type", "child-id")
- .setParent("parent-id").setSource("searchText", "quick brown fox").get();
+ "type=text,term_vector=with_positions_offsets,index_options=offsets"));
+ } else {
+ assertAcked(prepareCreate("test")
+ .addMapping("doc", "join_field", "type=join,parent-type=child-type",
+ "searchText", "type=text,term_vector=with_positions_offsets,index_options=offsets"));
+ }
+ createIndexRequest("test", "parent-type", "parent-id", null, "searchText", "quick brown fox").get();
+ createIndexRequest("test", "child-type", "child-id", "parent-id", "searchText", "quick brown fox").get();
refresh();
String[] highlightTypes = new String[] {"plain", "fvh", "unified"};
@@ -2038,13 +2139,18 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
}
public void testAliasesFilterWithHasChildQuery() throws Exception {
- assertAcked(prepareCreate("my-index")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent")
- .addMapping("child", "_parent", "type=parent")
- );
- client().prepareIndex("my-index", "parent", "1").setSource("{}", XContentType.JSON).get();
- client().prepareIndex("my-index", "child", "2").setSource("{}", XContentType.JSON).setParent("1").get();
+ if (legacy()) {
+ assertAcked(prepareCreate("my-index")
+ .addMapping("parent")
+ .addMapping("child", "_parent", "type=parent")
+ );
+ } else {
+ assertAcked(prepareCreate("my-index")
+ .addMapping("doc", "join_field", "type=join,parent=child")
+ );
+ }
+ createIndexRequest("my-index", "parent", "1", null).get();
+ createIndexRequest("my-index", "child", "2", "1").get();
refresh();
assertAcked(admin().indices().prepareAliases().addAlias("my-index", "filter1",
@@ -2060,154 +2166,4 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
}
- /*
- Test for https://github.com/elastic/elasticsearch/issues/3444
- */
- public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
- client().admin().indices().prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
- .addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON)
- .execute().actionGet();
- ensureGreen();
-
- BulkRequestBuilder builder = client().prepareBulk();
-
- // It's important to use JSON parsing here and request objects: issue 3444 is related to incomplete option parsing
- byte[] addParent = new BytesArray(
- "{" +
- " \"index\" : {" +
- " \"_index\" : \"test\"," +
- " \"_type\" : \"parent\"," +
- " \"_id\" : \"parent1\"" +
- " }" +
- "}" +
- "\n" +
- "{" +
- " \"field1\" : \"value1\"" +
- "}" +
- "\n").array();
-
- byte[] addChild = new BytesArray(
- "{" +
- " \"update\" : {" +
- " \"_index\" : \"test\"," +
- " \"_type\" : \"child\"," +
- " \"_id\" : \"child1\"," +
- " \"parent\" : \"parent1\"" +
- " }" +
- "}" +
- "\n" +
- "{" +
- " \"doc\" : {" +
- " \"field1\" : \"value1\"" +
- " }," +
- " \"doc_as_upsert\" : \"true\"" +
- "}" +
- "\n").array();
-
- builder.add(addParent, 0, addParent.length, XContentType.JSON);
- builder.add(addChild, 0, addChild.length, XContentType.JSON);
-
- BulkResponse bulkResponse = builder.get();
- assertThat(bulkResponse.getItems().length, equalTo(2));
- assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
- assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
-
- client().admin().indices().prepareRefresh("test").get();
-
- //we check that the _parent field was set on the child document by using the has parent query
- SearchResponse searchResponse = client().prepareSearch("test")
- .setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
- .get();
-
- assertNoFailures(searchResponse);
- assertSearchHits(searchResponse, "child1");
- }
-
- /*
- Test for https://github.com/elastic/elasticsearch/issues/3444
- */
- public void testBulkUpdateUpsertWithParent() throws Exception {
- assertAcked(prepareCreate("test")
- .setSettings("index.mapping.single_type", false)
- .addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
- .addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
- ensureGreen();
-
- BulkRequestBuilder builder = client().prepareBulk();
-
- byte[] addParent = new BytesArray(
- "{" +
- " \"index\" : {" +
- " \"_index\" : \"test\"," +
- " \"_type\" : \"parent\"," +
- " \"_id\" : \"parent1\"" +
- " }" +
- "}" +
- "\n" +
- "{" +
- " \"field1\" : \"value1\"" +
- "}" +
- "\n").array();
-
- byte[] addChild1 = new BytesArray(
- "{" +
- " \"update\" : {" +
- " \"_index\" : \"test\"," +
- " \"_type\" : \"child\"," +
- " \"_id\" : \"child1\"," +
- " \"parent\" : \"parent1\"" +
- " }" +
- "}" +
- "\n" +
- "{" +
- " \"script\" : {" +
- " \"inline\" : \"ctx._source.field2 = 'value2'\"" +
- " }," +
- " \"lang\" : \"" + InnerHitsIT.CustomScriptPlugin.NAME + "\"," +
- " \"upsert\" : {" +
- " \"field1\" : \"value1'\"" +
- " }" +
- "}" +
- "\n").array();
-
- byte[] addChild2 = new BytesArray(
- "{" +
- " \"update\" : {" +
- " \"_index\" : \"test\"," +
- " \"_type\" : \"child\"," +
- " \"_id\" : \"child1\"," +
- " \"parent\" : \"parent1\"" +
- " }" +
- "}" +
- "\n" +
- "{" +
- " \"script\" : \"ctx._source.field2 = 'value2'\"," +
- " \"upsert\" : {" +
- " \"field1\" : \"value1'\"" +
- " }" +
- "}" +
- "\n").array();
-
- builder.add(addParent, 0, addParent.length, XContentType.JSON);
- builder.add(addChild1, 0, addChild1.length, XContentType.JSON);
- builder.add(addChild2, 0, addChild2.length, XContentType.JSON);
-
- BulkResponse bulkResponse = builder.get();
- assertThat(bulkResponse.getItems().length, equalTo(3));
- assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
- assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
- assertThat(bulkResponse.getItems()[2].isFailed(), equalTo(true));
- assertThat(bulkResponse.getItems()[2].getFailure().getCause().getCause().getMessage(),
- equalTo("script_lang not supported [painless]"));
-
- client().admin().indices().prepareRefresh("test").get();
-
- SearchResponse searchResponse = client().prepareSearch("test")
- .setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
- .get();
-
- assertSearchHits(searchResponse, "child1");
- }
}
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java b/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java
index e95f3a7713..4b0a8e6781 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java
@@ -20,12 +20,12 @@
package org.elasticsearch.join.query;
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
-import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.similarities.PerFieldSimilarityWrapper;
@@ -87,6 +87,8 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
similarity = randomFrom("classic", "BM25");
+ // TODO: use a single type when inner hits have been changed to work with join field,
+ // this test randomly generates queries with inner hits
mapperService.merge(PARENT_TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(PARENT_TYPE,
STRING_FIELD_NAME, "type=text",
STRING_FIELD_NAME_2, "type=keyword",
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java b/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java
index 62ab92ac5e..c7b14d19e4 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java
@@ -72,6 +72,8 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
+ // TODO: use a single type when inner hits have been changed to work with join field,
+ // this test randomly generates queries with inner hits
mapperService.merge(PARENT_TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(PARENT_TYPE,
STRING_FIELD_NAME, "type=text",
STRING_FIELD_NAME_2, "type=keyword",
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/query/InnerHitsIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/query/InnerHitsIT.java
index 1d2e1c29e9..3459c9d352 100644
--- a/modules/parent-join/src/test/java/org/elasticsearch/join/query/InnerHitsIT.java
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/query/InnerHitsIT.java
@@ -547,7 +547,9 @@ public class InnerHitsIT extends ESIntegTestCase {
.addMapping("parent_type", "nested_type", "type=nested")
.addMapping("child_type", "_parent", "type=parent_type")
);
- createIndex("index2");
+ assertAcked(prepareCreate("index2")
+ .setSettings("index.mapping.single_type", false)
+ );
client().prepareIndex("index1", "parent_type", "1").setSource("nested_type", Collections.singletonMap("key", "value")).get();
client().prepareIndex("index1", "child_type", "2").setParent("1").setSource("{}", XContentType.JSON).get();
client().prepareIndex("index2", "type", "3").setSource("key", "value").get();
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/query/LegacyChildQuerySearchIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/query/LegacyChildQuerySearchIT.java
new file mode 100644
index 0000000000..445cb4be14
--- /dev/null
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/query/LegacyChildQuerySearchIT.java
@@ -0,0 +1,318 @@
+/*
+ * 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.join.query;
+
+import org.apache.lucene.search.join.ScoreMode;
+import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.search.SearchPhaseExecutionException;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.common.bytes.BytesArray;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+
+import java.io.IOException;
+import java.util.Map;
+
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery;
+import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
+import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.notNullValue;
+
+public class LegacyChildQuerySearchIT extends ChildQuerySearchIT {
+
+ @Override
+ protected boolean legacy() {
+ return true;
+ }
+
+ @Override
+ public Settings indexSettings() {
+ Settings indexSettings = super.indexSettings();
+ return Settings.builder()
+ .put(indexSettings)
+ .put("index.mapping.single_type", false)
+ .build();
+ }
+
+ public void testIndexChildDocWithNoParentMapping() throws IOException {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent")
+ .addMapping("child1"));
+ ensureGreen();
+
+ client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
+ try {
+ client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get();
+ fail();
+ } catch (IllegalArgumentException 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 (IllegalArgumentException e) {
+ assertThat(e.toString(), containsString("can't specify parent if no parent field has been configured"));
+ }
+
+ refresh();
+ }
+
+ public void testAddingParentToExistingMapping() throws 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 (IllegalArgumentException e) {
+ assertThat(e.toString(), containsString("The _parent field's type option can't be changed: [null]->[parent]"));
+ }
+ }
+
+ // Issue #5783
+ 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(new SearchSourceBuilder().query(hasChildQuery("posts",
+ QueryBuilders.matchQuery("field", "bar"), ScoreMode.None)))
+ .get();
+ assertHitCount(resp, 1L);
+ }
+
+ // Issue #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#type1"))
+ .get();
+
+ assertThat(response.getHits().getTotalHits(), equalTo(1L));
+ assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
+ }
+
+ public void testParentFieldToNonExistingType() {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent").addMapping("child", "_parent", "type=parent2"));
+ client().prepareIndex("test", "parent", "1").setSource("{}", XContentType.JSON).get();
+ client().prepareIndex("test", "child", "1").setParent("1").setSource("{}", XContentType.JSON).get();
+ refresh();
+
+ try {
+ client().prepareSearch("test")
+ .setQuery(hasChildQuery("child", matchAllQuery(), ScoreMode.None))
+ .get();
+ fail();
+ } catch (SearchPhaseExecutionException e) {
+ }
+ }
+
+ /*
+ Test for https://github.com/elastic/elasticsearch/issues/3444
+ */
+ public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
+ .addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
+ ensureGreen();
+
+ BulkRequestBuilder builder = client().prepareBulk();
+
+ // It's important to use JSON parsing here and request objects: issue 3444 is related to incomplete option parsing
+ byte[] addParent = new BytesArray(
+ "{" +
+ " \"index\" : {" +
+ " \"_index\" : \"test\"," +
+ " \"_type\" : \"parent\"," +
+ " \"_id\" : \"parent1\"" +
+ " }" +
+ "}" +
+ "\n" +
+ "{" +
+ " \"field1\" : \"value1\"" +
+ "}" +
+ "\n").array();
+
+ byte[] addChild = new BytesArray(
+ "{" +
+ " \"update\" : {" +
+ " \"_index\" : \"test\"," +
+ " \"_type\" : \"child\"," +
+ " \"_id\" : \"child1\"," +
+ " \"parent\" : \"parent1\"" +
+ " }" +
+ "}" +
+ "\n" +
+ "{" +
+ " \"doc\" : {" +
+ " \"field1\" : \"value1\"" +
+ " }," +
+ " \"doc_as_upsert\" : \"true\"" +
+ "}" +
+ "\n").array();
+
+ builder.add(addParent, 0, addParent.length, XContentType.JSON);
+ builder.add(addChild, 0, addChild.length, XContentType.JSON);
+
+ BulkResponse bulkResponse = builder.get();
+ assertThat(bulkResponse.getItems().length, equalTo(2));
+ assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
+ assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
+
+ client().admin().indices().prepareRefresh("test").get();
+
+ //we check that the _parent field was set on the child document by using the has parent query
+ SearchResponse searchResponse = client().prepareSearch("test")
+ .setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
+ .get();
+
+ assertNoFailures(searchResponse);
+ assertSearchHits(searchResponse, "child1");
+ }
+
+ /*
+ Test for https://github.com/elastic/elasticsearch/issues/3444
+ */
+ public void testBulkUpdateUpsertWithParent() throws Exception {
+ assertAcked(prepareCreate("test")
+ .addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
+ .addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
+ ensureGreen();
+
+ BulkRequestBuilder builder = client().prepareBulk();
+
+ byte[] addParent = new BytesArray(
+ "{" +
+ " \"index\" : {" +
+ " \"_index\" : \"test\"," +
+ " \"_type\" : \"parent\"," +
+ " \"_id\" : \"parent1\"" +
+ " }" +
+ "}" +
+ "\n" +
+ "{" +
+ " \"field1\" : \"value1\"" +
+ "}" +
+ "\n").array();
+
+ byte[] addChild1 = new BytesArray(
+ "{" +
+ " \"update\" : {" +
+ " \"_index\" : \"test\"," +
+ " \"_type\" : \"child\"," +
+ " \"_id\" : \"child1\"," +
+ " \"parent\" : \"parent1\"" +
+ " }" +
+ "}" +
+ "\n" +
+ "{" +
+ " \"script\" : {" +
+ " \"inline\" : \"ctx._source.field2 = 'value2'\"" +
+ " }," +
+ " \"lang\" : \"" + InnerHitsIT.CustomScriptPlugin.NAME + "\"," +
+ " \"upsert\" : {" +
+ " \"field1\" : \"value1'\"" +
+ " }" +
+ "}" +
+ "\n").array();
+
+ byte[] addChild2 = new BytesArray(
+ "{" +
+ " \"update\" : {" +
+ " \"_index\" : \"test\"," +
+ " \"_type\" : \"child\"," +
+ " \"_id\" : \"child1\"," +
+ " \"parent\" : \"parent1\"" +
+ " }" +
+ "}" +
+ "\n" +
+ "{" +
+ " \"script\" : \"ctx._source.field2 = 'value2'\"," +
+ " \"upsert\" : {" +
+ " \"field1\" : \"value1'\"" +
+ " }" +
+ "}" +
+ "\n").array();
+
+ builder.add(addParent, 0, addParent.length, XContentType.JSON);
+ builder.add(addChild1, 0, addChild1.length, XContentType.JSON);
+ builder.add(addChild2, 0, addChild2.length, XContentType.JSON);
+
+ BulkResponse bulkResponse = builder.get();
+ assertThat(bulkResponse.getItems().length, equalTo(3));
+ assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
+ assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
+ assertThat(bulkResponse.getItems()[2].isFailed(), equalTo(true));
+ assertThat(bulkResponse.getItems()[2].getFailure().getCause().getCause().getMessage(),
+ equalTo("script_lang not supported [painless]"));
+
+ client().admin().indices().prepareRefresh("test").get();
+
+ SearchResponse searchResponse = client().prepareSearch("test")
+ .setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
+ .get();
+
+ assertSearchHits(searchResponse, "child1");
+ }
+
+}
diff --git a/modules/parent-join/src/test/resources/rest-api-spec/test/11_parent_child.yml b/modules/parent-join/src/test/resources/rest-api-spec/test/11_parent_child.yml
new file mode 100644
index 0000000000..24f9931be0
--- /dev/null
+++ b/modules/parent-join/src/test/resources/rest-api-spec/test/11_parent_child.yml
@@ -0,0 +1,44 @@
+setup:
+ - do:
+ indices.create:
+ index: test
+ body:
+ mappings:
+ doc:
+ properties:
+ join_field:
+ type: join
+ parent: child
+
+---
+"Parent/child inner hits":
+ - skip:
+ version: " - 5.99.99"
+ reason: mapping.single_type was added in 6.0
+
+ - do:
+ index:
+ index: test
+ type: doc
+ id: 1
+ body: {"foo": "bar", "join_field": {"name" : "parent"} }
+
+ - do:
+ index:
+ index: test
+ type: doc
+ id: 2
+ routing: 1
+ body: {"bar": "baz", "join_field": { "name" : "child", "parent": "1"} }
+
+ - do:
+ indices.refresh: {}
+
+ # TODO: re-add inner hits here
+ - do:
+ search:
+ body: { "query" : { "has_child" : { "type" : "child", "query" : { "match_all" : {} } } } }
+ - match: { hits.total: 1 }
+ - match: { hits.hits.0._index: "test" }
+ - match: { hits.hits.0._type: "doc" }
+ - match: { hits.hits.0._id: "1" }