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);
}
相关推荐
文丑颜不良啊1 小时前
LeetCode2141~2160题目解析
java·leetcode
LabVIEW开发1 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
天天被压力2 小时前
【A股分钟级高频数据完全手册 #07】北交所历史分钟K线接口:京市Pro版分时批量
java·人工智能·python
天天被压力2 小时前
【A股分钟级高频数据完全手册 #08】股票日、分时数据接口对比:普通分时与Pro版差异实测
java·人工智能·python
特立独行的猫A2 小时前
AI 时代,我为什么推荐用 cj-tauri 开发桌面应用
java·后端·python
金銀銅鐵2 小时前
从一个类名到一张类图:用反射自动生成 PlantUML
java·后端·uml
nice_lcj5203 小时前
Java 并发容器入门:ConcurrentHashMap、CopyOnWriteArrayList、阻塞队列
java·面试·并发编程·阻塞队列·concurrenthashmap·copyonwritearraylist
微小的鱼3 小时前
Linux的渲染与显示系统链路
android·java·linux
若亦_4 小时前
Java中关于this的三种用法
java·开发语言·intellij-idea
山甫aa4 小时前
锁一篇搞定:乐观锁、悲观锁、CAS、数据库锁与分布式锁【从零开始的 Web 后端学习】
java·数据库·分布式·后端·学习·web