3
votes

i reindex data from es 2.4 to 5.6.
data in es 2.4 have 2 types,and the 2 type is parent-child relation.
when reindex it to es 5.6,the index only contains single type,the parent-child relation by using join type to resolving.
the data above works ok. the mapping example like this, it contains a join type:

"mappings": {
    "doc": {
        "properties": {
            "my_join_field": {
                "eager_global_ordinals": true,
                "type": "join",
                "relations": {
                    "question": "answer"
                }
            },
            "name": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "ignore_above": 256,
                        "type": "keyword"
                    }
                }
            }
        }
    }
}

how to mapping join type by using spring data elasticSearch: in old version code es 2.4,i can mapping it like this:

@Document(indexName = ParentEntity.INDEX, type = ParentEntity.PARENT_TYPE, shards = 1, replicas = 0, refreshInterval = "-1")
public class ParentEntity {

    public static final String INDEX = "parent-child";
    public static final String PARENT_TYPE = "parent-entity";
    public static final String CHILD_TYPE = "child-entity";

    @Id
    private String id;
    @Field(type = FieldType.Text, store = true)
    private String name;

    public ParentEntity() {
    }

    public ParentEntity(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return new ToStringCreator(this).append("id", id).append("name", name).toString();
    }

    @Document(indexName = INDEX, type = CHILD_TYPE, shards = 1, replicas = 0, refreshInterval = "-1")
    public static class ChildEntity {

        @Id
        private String id;
        @Field(type = FieldType.Text, store = true)
        @Parent(type = PARENT_TYPE)
        private String parentId;
        @Field(type = FieldType.Text, store = true)
        private String name;

        public ChildEntity() {
        }

        public ChildEntity(String id, String parentId, String name) {
            this.id = id;
            this.parentId = parentId;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public String getParentId() {
            return parentId;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return new ToStringCreator(this).append("id", id).append("parentId", parentId).append("name", name).toString();
        }
    }
}

how can i Mapping join type by using spring data elasticSearch v3.0.10?

Today, i tried the entity below to working at spring data elasticSearch 3.0.10:

@Document(indexName = "join_index", type = "join_mapping")
@Data
public class JoinEntity {
    @Id
    private String id;
    @Mapping(mappingPath = "/mappings/join_type.json")
    private Map<String,String> relationType;
    @Field(type = FieldType.Keyword)
    private String name;
    //@Parent(type = "question")
    @Field(type = FieldType.Keyword)
    private String parentId;
}

join_type.json below:

{
  "type": "join",
  "relations": {
    "question": "answer"
  }
}

it create index and put mapping work ok:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class ElasticsearchTemplateJoinTests {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Before
    public void before() {
        clean();
        elasticsearchTemplate.deleteIndex(JoinEntity.class);
        elasticsearchTemplate.createIndex(JoinEntity.class);
        elasticsearchTemplate.putMapping(JoinEntity.class);
        elasticsearchTemplate.refresh(JoinEntity.class);
    }

    @Test
    public void shouldCreateIndexAndMappingSuccess(){
        Map mapping = elasticsearchTemplate.getMapping(JoinEntity.class);
        assertThat(mapping, is(notNullValue()));

        Map properties = (Map) mapping.get("properties");
        assertThat(properties, is(notNullValue()));

        assertThat(properties.containsKey("name"), is(true));
        Map file = (Map) properties.get("relationType");
        assertThat(file, is(notNullValue()));
        assertThat(((String) file.get("type")), is("join"));
    }
}

when index parent work ok too,but index child it throws exception:

@Test 
public void shouldIndexParentAndChildSuccess(){
    JoinEntity parenEntity = new JoinEntity();
    parenEntity.setName("parent_name");
    parenEntity.setRelationType(Collections.singletonMap("name","question"));
    IndexQuery parentQuery = new IndexQueryBuilder().withId("11").withObject(parenEntity).build();
    final String id = elasticsearchTemplate.index(parentQuery);
    assertThat("11",is(id));
    JoinEntity childEntity = new JoinEntity();
    childEntity.setName("child_name");
    Map<String,String> joinRelation = new HashMap<>(2);
    joinRelation.put("name","answer");
    joinRelation.put("parent", "11");
    childEntity.setRelationType(joinRelation);
    childEntity.setParentId("11");
    IndexQuery childQuery = new IndexQueryBuilder().withId("22").withObject(childEntity).build();
    elasticsearchTemplate.index(childQuery);
}

exception:

MapperParsingException[failed to parse
]; nested: IllegalArgumentException[[routing] is missing for join field [relationType]];
    at org.elasticsearch.index.mapper.DocumentParser.wrapInMapperParsingException(DocumentParser.java:171)

how can i resolve this problem or Mapping the new version Parent-child relation correctly?thks!!

2
Did you find a way to do it? I'm wondering how to do it as wellEric Nascimento
i reindex them by two index, thus it will adapt future version,Some advanced and immature features suggest a reduction in usagesteven

2 Answers

2
votes

Elasticsearch needs the parent document routing parameter when you index child document check this

This is because both parent and child documents must be indexed in same shard to join to work.

However I couldn't figure out a way to solve this using Spring data elasticsearch. The only way that worked was using RestHighLevelClient

The recent version of Spring Data ElasticSearch had added support for this doc

Your child indexing would be something like,

    IndexRequest indexRequest = new IndexRequest();
    indexRequest.source(objectMapper.writeValueAsString(childEntity),XContentType.JSON);
    indexRequest.id("22"); //child doc id
    indexRequest.index(INDEX_NAME);
    indexRequest.type(INDEX_TYPE);
    indexRequest.routing("11"); //parent doc id
    restHighLevelClient.index(indexRequest);
0
votes

Finally, i gived up the parent-child relation, i split them into two separate indexs. some advance feature should be used less if not neccessary.