根据观察百度,京东等搜索框在输入一个字或者几个字时会有一个下拉框进行相关的查询这个就是补齐
首先需要在es中新建一个用于搜索的index,这个就相当于规定了搜索时的关键词
PUT /blog1
{
"mappings": {
"doc" : {
"properties" : {
"title" : {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"suggest" : {
"type" : "completion",
"analyzer": "ik_max_word"
}
}
},
"content": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
新建好index后可以添加几条数据
PUT /blog/1
{
"title": "中国人",
"content": "建设建设"
}
PUT /blog/2
{
"title": "中华人民共和国",
"content": "成立时间"
}
PUT /blog/3
{
"title": "中国的制造",
"content": "中国制造业世界领先"
}
添加完成后可以查询看看
GET /blog/_search
{
"suggest": {
"my-suggest" : {
"prefix" : "中国",
"completion" : {
"field" : "title.suggest"
}
}
}
}
如果出现的数据全是中国作为前缀的那么结果就正确
与springboot进行结合
@PostMapping("/searchsuggest")
public Object getSearchSuggest(String key) {
CompletionSuggestionBuilder suggestion = SuggestBuilders
.completionSuggestion("title.suggest").prefix(key).size(20).skipDuplicates(true);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("doc", suggestion);
//ESBlog1.class用于确定是哪一个index,ESBlog1是一个实体类
SearchResponse response = template.suggest(suggestBuilder, ESBlog1.class);
Suggest suggest = response.getSuggest();
Set<String> keywords = null;
if (suggest != null) {
keywords = new HashSet<>();
List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries
= suggest.getSuggestion("doc").getEntries();
for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : entries) {
for (Suggest.Suggestion.Entry.Option option: entry.getOptions()) {
// 最多返回9个数据, 每个长度最大为20
String keyword = option.getText().string();
if (!StringUtils.isEmpty(keyword) && keyword.length() <= 20) {
keywords.add(keyword);
if (keywords.size() >= 9) {
break;
}
}
}
}
}
return keywords;
}
ESBlog1实体类
package com.example.springbootelasticsearch.espojo;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Date;
@Data
//相当于表
@Document(indexName = "blog1",type = "doc",useServerConfiguration = true,createIndex = false)
public class ESBlog1 {
@Id
private Integer id;
//添加需要分词的字段用 @Field(type = FieldType.Text,analyzer = "ik_max_word")
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String author;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String content;
@Field(type = FieldType.Date,format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
private Date createTime;
@Field(type = FieldType.Date,format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
private Date updateTime;
}
如需了解es配置和logstash等配置可看我主页
下面是一些不成熟的建议:
如果全文检索和补齐搜索用同一个index可能全文检索的准确会出现误差,所以我在同一个es中新建两个index,这两个index的数据都是一致的,都是在数据库中实时的导入的,补齐搜索用一个,全文检索用一个,这样保证数据的一致也能将全文检索和补齐搜索分离。只是我自己在应用中出现的问题,仅供参考。
此情况下mysql.conf文件需要调整多添加一个elasticsearch模块
input{
jdbc{
#jdbc驱动包位置
jdbc_driver_library =>"/Users/zhangxianzeng/Downloads/elasticsearchquanbuwenjian/logstash-6.3.2/mysql-connector-java-8.0.16.jar"
#要使用的驱动包类,有过开发经验的都应该知道这个
jdbc_driver_class =>"com.mysql.jdbc.Driver"
#mysql数据库连接信息
jdbc_connection_string =>"jdbc:mysql://127.0.0.1:3306/blog"
#mysql用户名
jdbc_user =>"root"
#mysql密码
jdbc_password =>"zhangxian11"
#定时任务,多久执行一次查询,默认是一分钟,如何想要没有延迟,可以使用schedule =>"* * * * *"
schedule =>"* * * * *"
#清空上一次的sql_last_value记录
clean_run =>true
#你想要执行的语句
statement =>"SELECT * FROM t_blog WHERE update_time > :sql_last_value AND update_time < NOW() ORDER BY update_time desc"
}
}
output{
elasticsearch{
#es host:port
hosts=>["127.0.0.1:9200"]
#索引
index=>"blog"
#_id
document_id=>"%{id}"
}
//加一个elasticsearch模块
elasticsearch{
#es host:port
hosts=>["127.0.0.1:9200"]
#索引
index=>"blog1"
#_id
document_id=>"%{id}"
}
}
每一次重启logstash时需要将其data中的文件全部删除否则会报错
持续更新。。。。