三、实战:同步 ES 数据
3.1 定义检索模型
PassJava 这个项目可以用来配置题库,如果我们想通过关键字来搜索题库,该怎么做呢?
类似于百度搜索,输入几个关键字就可以搜到关联的结果,我们这个功能也是类似,通过 Elasticsearch 做检索引擎,后台管理界面和小程序作为搜索入口,只需要在小程序上输入关键字,就可以检索相关的题目和答案。
首先我们需要把题目和答案保存到 ES 中,在存之前,第一步是定义索引的模型,如下所示,模型中有 title
和 answer
字段,表示题目和答案。
"id": {
"type": "long"
},
"title": {
"type": "text",
"analyzer": "ik_smart"
},
"answer": {
"type": "text",
"analyzer": "ik_smart"
},
"typeName": {
"type": "keyword"
}
3.2 在 ES 中创建索引
上面我们已经定义了索引结构,接着就是在 ES 中创建索引。
在 Kibana 控制台中执行以下语句:
PUT question
{
"mappings" : {
"properties": {
"id": {
"type": "long"
},
"title": {
"type": "text",
"analyzer": "ik_smart"
},
"answer": {
"type": "text",
"analyzer": "ik_smart"
},
"typeName": {
"type": "keyword"
}
}
}
}
执行结果如下所示:
我们可以通过以下命令来查看 question 索引是否在 ES 中:
GET _cat/indices
执行结果如下图所示:
3.3 定义 ES model
上面我们定义 ES 的索引,接着就是定义索引对应的模型,将数据存到这个模型中,然后再存到 ES 中。
ES 模型如下,共四个字段:id、title、answer、typeName。和 ES 索引是相互对应的。
@Data
public class QuestionEsModel {
private Long id;
private String title;
private String answer;
private String typeName;
}
3.4 触发保存的时机
当我们在后台创建题目或保存题目时,先将数据保存到 mysql 数据库,然后再保存到 ES 中。
如下图所示,在管理后台创建题目时,触发保存数据到 ES 。
第一步,保存数据到 mysql 中,项目中已经包含此功能,就不再讲解了,直接进入第二步:保存数据到 ES 中。
而保存数据到 ES 中,需要将数据组装成 ES 索引对应的数据,所以我用了一个 ES model,先将数据保存到 ES model 中。
3.5 用 model 来组装数据
这里的关键代码时 copyProperties
,可以将 question
对象的数据取出,然后赋值到 ES model 中。不过 ES model 中还有些字段是 question 中没有的,所以需要单独拎出来赋值,比如 typeName 字段,question 对象中没有这个字段,它对应的字段是 question.type,所以我们把 type 取出来赋值到 ES model 的 typeName 字段上。如下图所示:
3.6 保存数据到 ES
我在 passjava-search 微服务中写了一个保存题目的 api 用来保存数据到 ES 中。
然后在 passjava-question 微服务中调用 search 微服务的保存 ES 的方法就可以了。
// 调用 passjava-search 服务,将数据发送到 ES 中保存。
searchFeignService.saveQuestion(esModel);
3.7 检验 ES 中是否创建成功
我们可以通过 kibana 的控制台来查看 question 索引中的文档。通过以下命令来查看:
GET question/_search
执行结果如下图所示,有一条记录:
另外大家有没有疑问:可以重复更新题目吗?
答案是可以的,保存到 ES 的数据是幂等的,因为保存的时候带了一个类似数据库主键的 id。