elasticsearch - 如何使用 spring 数据 elasticSearch 映射连接类型

标签 elasticsearch spring-data-elasticsearch

我将数据从 es 2.4 重新索引到 5.6。
es 2.4 中的数据有两种类型,两种类型是父子关系。
reindex到es 5.6时,索引只包含单一类型,父子关系使用join类型解析。
上面的数据工作正常。 像这样的映射示例,它包含一个连接类型:

"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"
                    }
                }
            }
        }
    }
}

如何使用 spring data elasticSearch 映射连接类型: 在旧版本代码 es 2.4 中,我可以这样映射它:

@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();
        }
    }
}

如何使用 spring data elasticSearch v3.0.10 映射连接类型?

今天,我尝试使用下面的实体在 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 如下:

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

它创建索引并使映射工作正常:

@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"));
    }
}

当索引父级也工作正常,但索引子级时它抛出异常:

@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)

如何解决这个问题或正确映射新版本的父子关系?thks!!

最佳答案

Elasticsearch 在索引子文档时需要父文档路由参数 check this

这是因为父文档和子文档必须在同一个分片中建立索引才能联合工作。

但是我想不出使用 Spring data elasticsearch 来解决这个问题的方法。唯一可行的方法是使用 RestHighLevelClient

最新版本的 Spring Data ElasticSearch 添加了对此的支持 doc

你的 child 索引会是这样的,

    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);

关于elasticsearch - 如何使用 spring 数据 elasticSearch 映射连接类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53170706/

相关文章:

python - ElasticSearch切片滚动限制(Python)

elasticsearch - 通过 curl 向 Elastic Watcher 发送请求

elasticsearch - 如何使用java api在elasticsearch中搜索特定日期和时间范围内的日志

java - Java 中的 ElasticSearch 库无法找到 AggregationBuilders.sum 方法

java - 如何在elasticsearch中创建不同的文档但ID相同

mysql - logstash-input-jdbc如何在语句中使用utf-8字符

elasticsearch - 组合 Elasticsearch 查询

java - 如何在spring-data-elasticsearch中将 “or”运算符与CriteriaQuery一起使用

spring-data-elasticsearch - 使用 spring 数据 Elasticsearch 禁用 _source 字段

spring - spring data elasticsearch中字段的唯一约束