Add a section named "relations" in the ParentJoinFieldMapper (#25248)

* Add a section named "relation" in the ParentJoinFieldMapper

This commit puts the parent/child definition in an inner section named "relation".
Mapping for the parent-join will look like this:

```
"join_field": {
  "type": "join"
  "relations":
    "parent": "child"
  }
}
```
This commit is contained in:
Jim Ferenczi 2017-06-15 14:56:20 +02:00 committed by GitHub
parent fe02829aac
commit 9ca33e2450
12 changed files with 353 additions and 151 deletions

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParserUtils;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.fielddata.IndexFieldData;
@ -162,7 +163,7 @@ public final class ParentJoinFieldMapper extends FieldMapper {
checkParentFields(name(), parentIdFields);
MetaJoinFieldMapper unique = new MetaJoinFieldMapper.Builder().build(context);
return new ParentJoinFieldMapper(name, fieldType, context.indexSettings(),
unique, Collections.unmodifiableList(parentIdFields));
unique, Collections.unmodifiableList(parentIdFields), eagerGlobalOrdinals);
}
}
@ -183,15 +184,21 @@ public final class ParentJoinFieldMapper extends FieldMapper {
iterator.remove();
continue;
}
final String parent = entry.getKey();
Set<String> children;
if (XContentMapValues.isArray(entry.getValue())) {
children = new HashSet<>(Arrays.asList(XContentMapValues.nodeStringArrayValue(entry.getValue())));
} else {
children = Collections.singleton(entry.getValue().toString());
if ("relations".equals(entry.getKey())) {
Map<String, Object> relations = XContentMapValues.nodeMapValue(entry.getValue(), "relations");
for (Iterator<Map.Entry<String, Object>> relIt = relations.entrySet().iterator(); relIt.hasNext(); ) {
Map.Entry<String, Object> relation = relIt.next();
final String parent = relation.getKey();
Set<String> children;
if (XContentMapValues.isArray(relation.getValue())) {
children = new HashSet<>(Arrays.asList(XContentMapValues.nodeStringArrayValue(relation.getValue())));
} else {
children = Collections.singleton(relation.getValue().toString());
}
builder.addParent(parent, children);
}
iterator.remove();
}
builder.addParent(parent, children);
iterator.remove();
}
return builder;
}
@ -235,16 +242,19 @@ public final class ParentJoinFieldMapper extends FieldMapper {
// The meta field that ensures that there is no other parent-join in the mapping
private MetaJoinFieldMapper uniqueFieldMapper;
private List<ParentIdFieldMapper> parentIdFields;
private boolean eagerGlobalOrdinals;
protected ParentJoinFieldMapper(String simpleName,
MappedFieldType fieldType,
Settings indexSettings,
MetaJoinFieldMapper uniqueFieldMapper,
List<ParentIdFieldMapper> parentIdFields) {
List<ParentIdFieldMapper> parentIdFields,
boolean eagerGlobalOrdinals) {
super(simpleName, fieldType, Defaults.FIELD_TYPE, indexSettings, MultiFields.empty(), null);
this.parentIdFields = parentIdFields;
this.uniqueFieldMapper = uniqueFieldMapper;
this.uniqueFieldMapper.setFieldMapper(this);
this.eagerGlobalOrdinals = eagerGlobalOrdinals;
}
@Override
@ -337,6 +347,7 @@ public final class ParentJoinFieldMapper extends FieldMapper {
if (conflicts.isEmpty() == false) {
throw new IllegalStateException("invalid update for join field [" + name() + "]:\n" + conflicts.toString());
}
this.eagerGlobalOrdinals = joinMergeWith.eagerGlobalOrdinals;
this.parentIdFields = Collections.unmodifiableList(newParentIdFields);
this.uniqueFieldMapper = (MetaJoinFieldMapper) uniqueFieldMapper.merge(joinMergeWith.uniqueFieldMapper, updateAllTypes);
uniqueFieldMapper.setFieldMapper(this);
@ -423,6 +434,8 @@ public final class ParentJoinFieldMapper extends FieldMapper {
@Override
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
builder.field("type", contentType());
builder.field("eager_global_ordinals", eagerGlobalOrdinals);
builder.startObject("relations");
for (ParentIdFieldMapper field : parentIdFields) {
if (field.getChildren().size() == 1) {
builder.field(field.getParentName(), field.getChildren().iterator().next());
@ -430,6 +443,7 @@ public final class ParentJoinFieldMapper extends FieldMapper {
builder.field(field.getParentName(), field.getChildren());
}
}
builder.endObject();
}
}

View File

@ -73,8 +73,9 @@ public class ChildrenIT extends ParentChildTestCase {
} else {
assertAcked(
prepareCreate("test")
.addMapping("doc", "category", "type=keyword", "join_field", "type=join,article=comment",
"commenter", "type=keyword")
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "article", "comment"),
"commenter", "keyword", "category", "keyword"))
);
}
@ -248,7 +249,9 @@ public class ChildrenIT extends ParentChildTestCase {
} else {
assertAcked(
prepareCreate(indexName)
.addMapping("doc", "join_field", "type=join,parent=child", "count", "type=long")
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child"),
"name", "keyword"))
);
}
@ -325,10 +328,12 @@ public class ChildrenIT extends ParentChildTestCase {
} 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")
.setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0))
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
masterType, childType),
"brand", "text", "name", "keyword", "material", "text", "color", "keyword", "size", "keyword"))
);
}
@ -400,8 +405,10 @@ public class ChildrenIT extends ParentChildTestCase {
} else {
assertAcked(
prepareCreate(indexName)
.addMapping("doc", "join_field", "type=join," + grandParentType + "=" + parentType + "," +
parentType + "=" + childType, "name", "type=keyword")
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
grandParentType, parentType, parentType, childType),
"name", "keyword"))
);
}
@ -449,8 +456,10 @@ public class ChildrenIT extends ParentChildTestCase {
} else {
assertAcked(
prepareCreate("index")
.addMapping("doc", "join_field", "type=join,parentType=childType", "name", "type=keyword",
"town", "type=keyword", "age", "type=integer")
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
"parentType", "childType"),
"name", "keyword", "town", "keyword", "age", "integer"))
);
}
List<IndexRequestBuilder> requests = new ArrayList<>();

View File

@ -49,9 +49,11 @@ public class ParentJoinFieldSubFetchPhaseTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child")
.field("product", "item")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.field("product", "item")
.endObject()
.endObject()
.endObject()
.endObject().string();

View File

@ -50,7 +50,9 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.startObject("relations")
.field("parent", "child")
.endObject()
.endObject()
.endObject()
.endObject().string();
@ -97,8 +99,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.endObject()
.endObject()
.endObject()
.endObject().string();
@ -176,8 +180,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.startObject("relations")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.endObject()
.endObject()
.endObject().endObject().string();
IndexService indexService = createIndex("test");
@ -189,7 +195,9 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.array("child", "grand_child1", "grand_child2")
.startObject("relations")
.array("child", "grand_child1", "grand_child2")
.endObject()
.endObject()
.endObject().endObject().string();
IllegalStateException exc = expectThrows(IllegalStateException.class,
@ -202,8 +210,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child1")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child1")
.endObject()
.endObject()
.endObject().endObject().string();
IllegalStateException exc = expectThrows(IllegalStateException.class,
@ -216,9 +226,11 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("uber_parent", "parent")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.startObject("relations")
.field("uber_parent", "parent")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.endObject()
.endObject()
.endObject().endObject().string();
IllegalStateException exc = expectThrows(IllegalStateException.class,
@ -230,10 +242,12 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
{
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.field("grand_child2", "grand_grand_child")
.field("type", "join")
.startObject("relations")
.field("parent", "child")
.array("child", "grand_child1", "grand_child2")
.field("grand_child2", "grand_grand_child")
.endObject()
.endObject()
.endObject().endObject().string();
IllegalStateException exc = expectThrows(IllegalStateException.class,
@ -246,8 +260,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.array("parent", "child", "child2")
.array("child", "grand_child1", "grand_child2")
.startObject("relations")
.array("parent", "child", "child2")
.array("child", "grand_child1", "grand_child2")
.endObject()
.endObject()
.endObject().endObject().string();
docMapper = indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
@ -264,9 +280,11 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
final String updateMapping = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.array("parent", "child", "child2")
.array("child", "grand_child1", "grand_child2")
.array("other", "child_other1", "child_other2")
.startObject("relations")
.array("parent", "child", "child2")
.array("child", "grand_child1", "grand_child2")
.array("other", "child_other1", "child_other2")
.endObject()
.endObject()
.endObject().endObject().string();
docMapper = indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
@ -288,7 +306,9 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.startObject("relations")
.field("parent", "child")
.endObject()
.endObject()
.endObject()
.endObject()
@ -308,7 +328,9 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("fields")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.startObject("relations")
.field("parent", "child")
.endObject()
.endObject()
.endObject()
.endObject()
@ -328,12 +350,16 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.endObject()
.endObject()
.startObject("another_join_field")
.field("type", "join")
.field("product", "item")
.startObject("relations")
.field("product", "item")
.endObject()
.endObject()
.endObject()
.endObject().string();
@ -347,8 +373,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.endObject()
.endObject()
.endObject()
.endObject().string();
@ -372,8 +400,10 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", "child")
.field("child", "grand_child")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.endObject()
.endObject()
.endObject()
.endObject().string();
@ -392,12 +422,14 @@ public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
.startObject("join_field")
.field("type", "join")
.field("eager_global_ordinals", false)
.field("parent", "child")
.field("child", "grand_child")
.startObject("relations")
.field("parent", "child")
.field("child", "grand_child")
.endObject()
.endObject()
.endObject()
.endObject().string();
docMapper = service.mapperService().merge("type", new CompressedXContent(mapping),
service.mapperService().merge("type", new CompressedXContent(mapping),
MapperService.MergeReason.MAPPING_UPDATE, false);
assertFalse(service.mapperService().fullName("join_field").eagerGlobalOrdinals());
assertNotNull(service.mapperService().fullName("join_field#parent"));

View File

@ -29,7 +29,6 @@ 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.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.IdsQueryBuilder;
import org.elasticsearch.index.query.InnerHitBuilder;
@ -102,7 +101,8 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("grandchild", "_parent", "type=child"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child,child=grandchild"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
"parent", "child", "child", "grandchild")));
}
ensureGreen();
@ -164,7 +164,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("test", "_parent", "type=foo"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,foo=test"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "foo", "test")));
}
ensureGreen();
@ -188,7 +188,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -295,7 +295,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
List<IndexRequestBuilder> builders = new ArrayList<>();
@ -339,7 +339,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
Map<String, Set<String>> parentToChildren = new HashMap<>();
@ -393,7 +393,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -467,7 +467,9 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.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"));
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child"),
"c_field", "keyword")));
}
ensureGreen();
@ -511,7 +513,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
// index simple data
@ -551,7 +553,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -584,7 +586,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -613,7 +615,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -650,7 +652,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -724,7 +726,9 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("doc", jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", new String[] {"child", "child1"})
.startObject("relations")
.field("parent", new String[] {"child", "child1"})
.endObject()
.endObject()
.endObject().endObject().endObject()
));
@ -818,7 +822,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -863,7 +867,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -893,7 +897,6 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("2"));
}
@AwaitsFix(bugUrl = "wait for inner hits to be fixed")
public void testHasChildInnerHitsHighlighting() throws Exception {
if (legacy()) {
assertAcked(prepareCreate("test")
@ -901,7 +904,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -931,7 +934,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -969,7 +972,8 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.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"));
.addMapping("doc", addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child"),
"c_field", "keyword", "p_field", "keyword")));
}
ensureGreen();
@ -1022,7 +1026,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1089,7 +1093,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1124,7 +1128,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
} else {
assertAcked(prepareCreate("test")
.setSettings("index.refresh_interval", -1)
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1195,7 +1199,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.put(indexSettings())
.put("index.refresh_interval", -1)
)
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1223,7 +1227,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1294,9 +1298,11 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
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"})
.field("type", "join")
.startObject("relations")
.field("grandparent", "parent")
.field("parent", new String[] {"child_type_one", "child_type_two"})
.endObject()
.endObject()
.endObject().endObject().endObject()
));
@ -1350,7 +1356,9 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child", "objects", "type=nested"));
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child"),
"objects", "nested")));
}
ensureGreen();
@ -1396,7 +1404,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1503,7 +1511,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
} else {
assertAcked(prepareCreate("test")
.setSettings("index.refresh_interval", -1)
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1551,7 +1559,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
for (int i = 0; i < 10; i++) {
@ -1599,7 +1607,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -1683,7 +1691,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
ensureGreen();
@ -2001,7 +2009,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
.addMapping("parent-type").addMapping("child-type", "_parent", "type=parent-type"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent-type=child-type"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent-type", "child-type")));
}
createIndexRequest("test", "child-type", "child-id", "parent-id").get();
createIndexRequest("test", "parent-type", "parent-id", null).get();
@ -2017,7 +2025,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
assertSearchHits(searchResponse, "child-id");
}
public void testHighlightersIgnoreParentChild() {
public void testHighlightersIgnoreParentChild() throws IOException {
if (legacy()) {
assertAcked(prepareCreate("test")
.addMapping("parent-type", "searchText", "type=text,term_vector=with_positions_offsets,index_options=offsets")
@ -2025,8 +2033,20 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
"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"));
.addMapping("doc", jsonBuilder().startObject().startObject("properties")
.startObject("join_field")
.field("type", "join")
.startObject("relations")
.field("parent-type", "child-type")
.endObject()
.endObject()
.startObject("searchText")
.field("type", "text")
.field("term_vector", "with_positions_offsets")
.field("index_options", "offsets")
.endObject()
.endObject().endObject()
));
}
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();
@ -2069,8 +2089,7 @@ public class ChildQuerySearchIT extends ParentChildTestCase {
);
} else {
assertAcked(prepareCreate("my-index")
.addMapping("doc", "join_field", "type=join,parent=child")
);
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
createIndexRequest("my-index", "parent", "1", null).get();
createIndexRequest("my-index", "child", "2", "1").get();

View File

@ -32,10 +32,10 @@ import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.similarities.PerFieldSimilarityWrapper;
import org.apache.lucene.search.similarities.Similarity;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.IdFieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.IdsQueryBuilder;
@ -63,6 +63,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
@ -95,17 +96,42 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
similarity = randomFrom("classic", "BM25");
mapperService.merge(TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(TYPE,
"join_field", "type=join," + PARENT_DOC + "=" + CHILD_DOC,
STRING_FIELD_NAME, "type=text",
STRING_FIELD_NAME_2, "type=keyword",
"custom_string", "type=text,similarity=" + similarity,
INT_FIELD_NAME, "type=integer",
DOUBLE_FIELD_NAME, "type=double",
BOOLEAN_FIELD_NAME, "type=boolean",
DATE_FIELD_NAME, "type=date",
OBJECT_FIELD_NAME, "type=object"
).string()), MapperService.MergeReason.MAPPING_UPDATE, false);
XContentBuilder mapping = jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.startObject("relations")
.field(PARENT_DOC, CHILD_DOC)
.endObject()
.endObject()
.startObject(STRING_FIELD_NAME)
.field("type", "text")
.endObject()
.startObject(STRING_FIELD_NAME_2)
.field("type", "keyword")
.endObject()
.startObject(INT_FIELD_NAME)
.field("type", "integer")
.endObject()
.startObject(DOUBLE_FIELD_NAME)
.field("type", "double")
.endObject()
.startObject(BOOLEAN_FIELD_NAME)
.field("type", "boolean")
.endObject()
.startObject(DATE_FIELD_NAME)
.field("type", "date")
.endObject()
.startObject(OBJECT_FIELD_NAME)
.field("type", "object")
.endObject()
.startObject("custom_string")
.field("type", "text")
.field("similarity", similarity)
.endObject()
.endObject().endObject().endObject();
mapperService.merge(TYPE,
new CompressedXContent(mapping.string()), MapperService.MergeReason.MAPPING_UPDATE, false);
}
/**

View File

@ -55,6 +55,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
@ -83,16 +84,38 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
mapperService.merge(TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(TYPE,
"join_field", "type=join," + PARENT_DOC + "=" + CHILD_DOC,
STRING_FIELD_NAME, "type=text",
STRING_FIELD_NAME_2, "type=keyword",
INT_FIELD_NAME, "type=integer",
DOUBLE_FIELD_NAME, "type=double",
BOOLEAN_FIELD_NAME, "type=boolean",
DATE_FIELD_NAME, "type=date",
OBJECT_FIELD_NAME, "type=object"
).string()), MapperService.MergeReason.MAPPING_UPDATE, false);
XContentBuilder mapping = jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.startObject("relations")
.field(PARENT_DOC, CHILD_DOC)
.endObject()
.endObject()
.startObject(STRING_FIELD_NAME)
.field("type", "text")
.endObject()
.startObject(STRING_FIELD_NAME_2)
.field("type", "keyword")
.endObject()
.startObject(INT_FIELD_NAME)
.field("type", "integer")
.endObject()
.startObject(DOUBLE_FIELD_NAME)
.field("type", "double")
.endObject()
.startObject(BOOLEAN_FIELD_NAME)
.field("type", "boolean")
.endObject()
.startObject(DATE_FIELD_NAME)
.field("type", "date")
.endObject()
.startObject(OBJECT_FIELD_NAME)
.field("type", "object")
.endObject()
.endObject().endObject().endObject();
mapperService.merge(TYPE,
new CompressedXContent(mapping.string()), MapperService.MergeReason.MAPPING_UPDATE, false);
}
/**

View File

@ -90,9 +90,22 @@ public class InnerHitsIT extends ParentChildTestCase {
);
} else {
assertAcked(prepareCreate("articles")
.addMapping("doc", "join_field", "type=join,article=comment", "title", "type=text",
"message", "type=text,fielddata=true")
);
.addMapping("doc", jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.startObject("relations")
.field("article", "comment")
.endObject()
.endObject()
.startObject("title")
.field("type", "text")
.endObject()
.startObject("message")
.field("type", "text")
.field("fielddata", true)
.endObject()
.endObject().endObject().endObject()
));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
@ -173,8 +186,10 @@ public class InnerHitsIT extends ParentChildTestCase {
assertAcked(prepareCreate("idx")
.addMapping("doc", jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.field("parent", new String[] {"child1", "child2"})
.field("type", "join")
.startObject("relations")
.field("parent", new String[] {"child1", "child2"})
.endObject()
.endObject()
.endObject().endObject().endObject()
));
@ -261,8 +276,8 @@ public class InnerHitsIT extends ParentChildTestCase {
);
} else {
assertAcked(prepareCreate("stack")
.addMapping("doc", "join_field", "type=join,question=answer", "body", "type=text")
);
.addMapping("doc", addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "question", "answer"),
"body", "text")));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(createIndexRequest("stack", "question", "1", null, "body", "I'm using HTTPS + Basic authentication "
@ -308,9 +323,9 @@ public class InnerHitsIT extends ParentChildTestCase {
);
} else {
assertAcked(prepareCreate("articles")
.addMapping("doc", "join_field", "type=join,article=comment,comment=remark",
"title", "type=text", "message", "type=text")
);
.addMapping("doc",
addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
"article", "comment", "comment", "remark"), "title", "text", "message", "text")));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
@ -376,10 +391,9 @@ public class InnerHitsIT extends ParentChildTestCase {
.addMapping("baron", "_parent", "type=earl")
);
} else {
assertAcked(
prepareCreate("royals")
.addMapping("doc", "join_field", "type=join,king=prince,prince=duke,duke=earl,earl=baron")
);
assertAcked(prepareCreate("royals")
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
"king", "prince", "prince", "duke", "duke", "earl", "earl", "baron")));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
@ -452,7 +466,7 @@ public class InnerHitsIT extends ParentChildTestCase {
.addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("index")
.addMapping("doc", "join_field", "type=join,parent=child"));
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(createIndexRequest("index", "parent", "1", null));
@ -495,7 +509,8 @@ public class InnerHitsIT extends ParentChildTestCase {
if (legacy()) {
assertAcked(prepareCreate("index1").addMapping("child", "_parent", "type=parent"));
} else {
assertAcked(prepareCreate("index1").addMapping("doc", "join_field", "type=join,parent=child"));
assertAcked(prepareCreate("index1")
.addMapping("doc", buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent", "child")));
}
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(createIndexRequest("index1", "parent", "1", null));
@ -517,7 +532,8 @@ public class InnerHitsIT extends ParentChildTestCase {
.addMapping("child_type", "_parent", "type=parent_type", "nested_type", "type=nested"));
} else {
assertAcked(prepareCreate("test")
.addMapping("doc", "join_field", "type=join,parent_type=child_type", "nested_type", "type=nested"));
.addMapping("doc", addFieldMappings(buildParentJoinFieldMappingFromSimplifiedDef("join_field", true,
"parent_type", "child_type"), "nested_type", "nested")));
}
createIndexRequest("test", "parent_type", "1", null, "key", "value").get();
createIndexRequest("test", "child_type", "2", "1", "nested_type", Collections.singletonMap("key", "value")).get();
@ -545,7 +561,9 @@ public class InnerHitsIT extends ParentChildTestCase {
);
} else {
assertAcked(prepareCreate("index1")
.addMapping("doc", "join_field", "type=join,parent_type=child_type", "nested_type", "type=nested")
.addMapping("doc", addFieldMappings(
buildParentJoinFieldMappingFromSimplifiedDef("join_field", true, "parent_type", "child_type"),
"nested_type", "nested"))
);
}
assertAcked(prepareCreate("index2"));

View File

@ -84,6 +84,39 @@ public abstract class ParentChildTestCase extends ESIntegTestCase {
return createIndexRequest(index, type, id, parentId, source);
}
public static Map<String, Object> buildParentJoinFieldMappingFromSimplifiedDef(String joinFieldName,
boolean eagerGlobalOrdinals,
String... relations) {
Map<String, Object> fields = new HashMap<>();
Map<String, Object> joinField = new HashMap<>();
joinField.put("type", "join");
joinField.put("eager_global_ordinals", eagerGlobalOrdinals);
Map<String, Object> relationMap = new HashMap<>();
for (int i = 0; i < relations.length; i+=2) {
String[] children = relations[i+1].split(",");
if (children.length > 1) {
relationMap.put(relations[i], children);
} else {
relationMap.put(relations[i], children[0]);
}
}
joinField.put("relations", relationMap);
fields.put(joinFieldName, joinField);
return Collections.singletonMap("properties", fields);
}
@SuppressWarnings("unchecked")
public static Map<String, Object> addFieldMappings(Map<String, Object> map, String... fields) {
Map<String, Object> propsMap = (Map<String, Object>) map.get("properties");
for (int i = 0; i < fields.length; i+=2) {
String field = fields[i];
String type = fields[i + 1];
propsMap.put(field, Collections.singletonMap("type", type));
}
return map;
}
private IndexRequestBuilder createIndexRequest(String index, String type, String id, String parentId, Map<String, Object> source) {
String name = type;
if (legacy() == false) {

View File

@ -31,6 +31,7 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.TypeFieldMapper;
import org.elasticsearch.index.query.QueryShardException;
@ -44,6 +45,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -71,15 +73,38 @@ public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQue
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
mapperService.merge(TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(TYPE,
STRING_FIELD_NAME, "type=text",
INT_FIELD_NAME, "type=integer",
DOUBLE_FIELD_NAME, "type=double",
BOOLEAN_FIELD_NAME, "type=boolean",
DATE_FIELD_NAME, "type=date",
OBJECT_FIELD_NAME, "type=object",
JOIN_FIELD_NAME, "type=join,parent=child"
).string()), MapperService.MergeReason.MAPPING_UPDATE, false);
XContentBuilder mapping = jsonBuilder().startObject().startObject("doc").startObject("properties")
.startObject("join_field")
.field("type", "join")
.startObject("relations")
.field("parent", "child")
.endObject()
.endObject()
.startObject(STRING_FIELD_NAME)
.field("type", "text")
.endObject()
.startObject(STRING_FIELD_NAME_2)
.field("type", "keyword")
.endObject()
.startObject(INT_FIELD_NAME)
.field("type", "integer")
.endObject()
.startObject(DOUBLE_FIELD_NAME)
.field("type", "double")
.endObject()
.startObject(BOOLEAN_FIELD_NAME)
.field("type", "boolean")
.endObject()
.startObject(DATE_FIELD_NAME)
.field("type", "date")
.endObject()
.startObject(OBJECT_FIELD_NAME)
.field("type", "object")
.endObject()
.endObject().endObject().endObject();
mapperService.merge(TYPE,
new CompressedXContent(mapping.string()), MapperService.MergeReason.MAPPING_UPDATE, false);
}
@Override

View File

@ -10,13 +10,14 @@ setup:
properties:
join_field:
type: join
parent: child
relations:
parent: child
---
"Parent/child inner hits":
- skip:
version: " - 5.4.99"
reason: mapping.single_type was added in 5.5
version: " - 5.6.99"
reason: parent-join was added in 5.6. Disabled BWC tests until https://github.com/elastic/elasticsearch/pull/25248 is merged
- do:
index:

View File

@ -8,7 +8,7 @@ setup:
mappings:
doc:
properties:
join_field: { "type": "join", "parent": "child", "child": "grand_child" }
join_field: { "type": "join", "relations": { "parent": "child", "child": "grand_child" } }
- do:
index:
@ -107,8 +107,8 @@ setup:
---
"Test parent_id query":
- skip:
version: " - 5.5.99"
reason: parent-join was added in 5.6
version: " - 5.6.99"
reason: parent-join was added in 5.6. Disabled BWC tests until https://github.com/elastic/elasticsearch/pull/25248 is merged
- do:
search: