Spring Data访问Elasticsearch----Join-Type的实现

Spring Data访问Elasticsearch----Join-Type的实现

Spring Data Elasticsearch支持 Join数据类型,用于创建相应的索引映射和存储相关信息。

一、设置数据

对于在父子连接关系中使用的实体,它必须具有JoinField类型的属性,并且必须对其进行注解。让我们假设一个Statement实体,其中的语句可能是一个问题、一个答案、一个评论或一个投票(在这个例子中也显示了一个Builder,它不是必需的,但稍后在示例代码中使用):

java 复制代码
@Document(indexName = "statements")
@Routing("routing")                                                                       --------1
public class Statement {
    @Id
    private String id;

    @Field(type = FieldType.Text)
    private String text;

    @Field(type = FieldType.Keyword)
    private String routing;

    @JoinTypeRelations(
        relations =
            {
                @JoinTypeRelation(parent = "question", children = {"answer", "comment"}), --------2
                @JoinTypeRelation(parent = "answer", children = "vote")                   --------3
            }
    )
    private JoinField<String> relation;                                                   --------4

    private Statement() {
    }

    public static StatementBuilder builder() {
        return new StatementBuilder();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getRouting() {
        return routing;
    }

    public void setRouting(Routing routing) {
        this.routing = routing;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public JoinField<String> getRelation() {
        return relation;
    }

    public void setRelation(JoinField<String> relation) {
        this.relation = relation;
    }

    public static final class StatementBuilder {
        private String id;
        private String text;
        private String routing;
        private JoinField<String> relation;

        private StatementBuilder() {
        }

        public StatementBuilder withId(String id) {
            this.id = id;
            return this;
        }

        public StatementBuilder withRouting(String routing) {
            this.routing = routing;
            return this;
        }

        public StatementBuilder withText(String text) {
            this.text = text;
            return this;
        }

        public StatementBuilder withRelation(JoinField<String> relation) {
            this.relation = relation;
            return this;
        }

        public Statement build() {
            Statement statement = new Statement();
            statement.setId(id);
            statement.setRouting(routing);
            statement.setText(text);
            statement.setRelation(relation);
            return statement;
        }
    }
}

1. 有关路由相关信息,请参阅[路由值](https://blog.csdn.net/gabriel_wang_sh/article/details/136839367)
2. 一个问题可以有答案和评论
3. 答案可以有投票
4. JoinField属性用于将关系的名称(问题、答案、评论或投票)与父id相结合。泛型类型必须与@Id注解的属性相同。

Spring Data Elasticsearch将为这个类构建以下映射:

json 复制代码
{
  "statements": {
    "mappings": {
      "properties": {
        "_class": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "routing": {
          "type": "keyword"
        },
        "relation": {
          "type": "join",
          "eager_global_ordinals": true,
          "relations": {
            "question": [
              "answer",
              "comment"
            ],
            "answer": "vote"
          }
        },
        "text": {
          "type": "text"
        }
      }
    }
  }
}

二、存储数据

给定该类的存储库,下面的代码插入一个问题,两个答案,一个评论和一个投票:

java 复制代码
void init() {
    repository.deleteAll();

    Statement savedWeather = repository.save(
        Statement.builder()
            .withText("How is the weather?")
            .withRelation(new JoinField<>("question"))                     --------1     
            .build());

    Statement sunnyAnswer = repository.save(
        Statement.builder()
            .withText("sunny")
            .withRelation(new JoinField<>("answer", savedWeather.getId())) --------2     
            .build());

    repository.save(
        Statement.builder()
            .withText("rainy")
            .withRelation(new JoinField<>("answer", savedWeather.getId())) --------3     
            .build());

    repository.save(
        Statement.builder()
            .withText("I don't like the rain")
            .withRelation(new JoinField<>("comment", savedWeather.getId())) --------4     
            .build());

    repository.save(
        Statement.builder()
            .withText("+1 for the sun")
            ,withRouting(savedWeather.getId())
            .withRelation(new JoinField<>("vote", sunnyAnswer.getId()))     --------5    
            .build());
}

1. 创建问题陈述
2. 问题的第一个答案
3. 第二个答案
4. 对这个问题的评论
5. 投票给第一个答案,这需要将路由设置为weather文档,请参阅[路由值](https://blog.csdn.net/gabriel_wang_sh/article/details/136839367)。

三、检索数据

目前,必须使用native查询来查询数据,因此没有标准存储库方法的支持。可以使用自定义存储库实现

以下代码示例显示了如何使用ElasticsearchOperations实例检索所有有投票的条目(必须是answers,因为只有answers才能有投票):

java 复制代码
SearchHits<Statement> hasVotes() {

	Query query = NativeQuery.builder()
		.withQuery(co.elastic.clients.elasticsearch._types.query_dsl.Query.of(qb -> qb
			.hasChild(hc -> hc
				.queryName("vote")
				.query(matchAllQueryAsQuery())
				.scoreMode(ChildScoreMode.None)
			)))
		.build();

	return operations.search(query, Statement.class);
}
相关推荐
chxii几秒前
6.2字节流
java·开发语言
不务专业的程序员--阿飞10 分钟前
【SQL 如何解锁递归】
java·数据库·sql
嘵奇16 分钟前
Spring Boot拦截器详解:原理、实现与应用场景
java·spring boot·后端
八股文领域大手子17 分钟前
Java死锁排查:线上救火实战指南
java·开发语言·面试
jackson凌23 分钟前
【Java学习笔记】finalize方法
java·笔记·学习
fanTuanye26 分钟前
redis 缓存穿透,缓存击穿,缓存雪崩
java·redis·缓存
神秘的t44 分钟前
Spring Web MVC————入门(2)
java·spring·mvc
开开心心就好1 小时前
高效全能PDF工具,支持OCR识别
java·前端·python·pdf·ocr·maven·jetty
冷心笑看丽美人1 小时前
Spring MVC数据绑定和响应 你了解多少?
java·spring·mvc
XQ丶YTY1 小时前
大二java第一面小厂(挂)
java·开发语言·笔记·学习·面试