全文搜索引擎elasticSearch
es尿崩式更新,三两天就发布一个新版本,到现在三两年已经从1.0.0到7.x上百个版本,版本与springboot对应、语法都有不同,文档还不好找,坑
第五部分记录6.2.2版本的增删改查操作、嵌套,网上现有的代码基本都不能用
零 有价值的参考资料
一 安装
二 功能用处
* 搜索引擎:只需要elasticsearch本体,webapp端引入依赖,通过相关api交互增删改查;
* 聚合数据分析:需要kibana可视化、logstash日志插件,分析数据;
三 结构
与数据库区分,有自己的一套库专门用于检索,通过logstash或业务同步操作来同步数据。
四 整合sb
1 pom依赖
org.springframework.boot
spring-boot-starter-data-elasticsearch
2 配置
# ELASTICSEARCH (ElasticsearchProperties)
# Elasticsearch cluster name.
spring.data.elasticsearch.cluster-name=elasticsearch_coldxiangyu
# Comma-separated list of cluster node addresses.
spring.data.elasticsearch.cluster-nodes= 127.0.0.1:9300
# Whether to enable Elasticsearch repositories.
spring.data.elasticsearch.repositories.enabled=true
3 建立接口
package com.coldxiangyu.elasticsearch.repository;
import com.coldxiangyu.elasticsearch.bean.QuestionBean;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* 接口关系:
* ElasticsearchRepository --> ElasticsearchCrudRepository --> PagingAndSortingRepository --> CrudRepository
*/
public interface QuestionRepository extends ElasticsearchRepository {
//Optional findById(String id);
}
ps:
findAll——查询所有数据,返回的是个迭代器
findById——根据id(主键)查询
1 例子
findByAaBetweenOrderByBbDesc——查询Aa字段介于两个入参之间(包含边界)的数据,按Bb倒序排序
findByNameStartingWith——查询Name字段开头为入参的数据
Long countByLastname(String lastname)——计数
2 为明确嵌套的属性,可使用_分隔
findByAaBbCc 会识别为AaBbCc,找不到再识别AaBb和Cc。可直接写findByAa_BbCc,就会寻找Aa和BbCc
3 特殊条件
Page findByLastname(String lastname, Pageable pageable);
Slice findByLastname(String lastname, Pageable pageable);
List findByLastname(String lastname, Sort sort);
List findByLastname(String lastname, Pageable pageable);
第一个方法允许你传递一个org.springframework.data.domain.Pageable实例到查询方法来动态的进行分页。一个Page知道总数量和一共多少页可用。它之所以知道这些是因为底层框架触发了一个技计数查询来计算全部的数量。根据使用的数据存储技术不同这可能消耗很大时间,可以使用Slice来替代它。Slice只知道是否存在下一个Slice可用,这将会非常适合查询超大结果集。
排序操作也可以通过Pageable接口来处理。如果你仅仅需要排序那么可以使用org.springframework.data.domain.Sort实例作为方法参数。如你所见,查询方法也可以仅仅返回一个List。这将约束查询方法只查询给定范围的数据。
来源:https://www.jianshu.com/p/27e1d583aafb 1.4章
@Query("{\"bool\" : {\"must\" : {\"match\" : {\"name\" : \"?0\"}}}}")
public List findByNameLike(String name);
根据入参完全匹配name字段查询
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withFilter(regexpQuery("title", ".*data.*"))
.build();
List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
查询title字段包含data的数据
repository.findAll(new PageRequest(1, 20))
4 调用接口
package com.coldxiangyu.elasticsearch.service.impl;
import com.coldxiangyu.elasticsearch.bean.QuestionBean;
import com.coldxiangyu.elasticsearch.repository.QuestionRepository;
import com.coldxiangyu.elasticsearch.service.QuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service("questionService")
public class QuestionServiceImpl implements QuestionService {
@Autowired
@Qualifier("questionRepository")
private QuestionRepository questionRepository;
@Override
public Optional findById(String id) {
//CrudRepository中的方法
return questionRepository.findById(id);
}
@Override
public QuestionBean save(QuestionBean blog) {
return questionRepository.save(blog);
}
}
5 相关bean实体
package com.coldxiangyu.elasticsearch.bean;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "qa_applicant_to_attachment", type = "_doc")
public class ApplicantAttachmentBean {
@Id
private String id;
private String applicantId;
private String attachmentId;
public ApplicantAttachmentBean(){}
public ApplicantAttachmentBean(String id, String applicantId, String attachmentId) {
this.id = id;
this.applicantId = applicantId;
this.attachmentId = attachmentId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getApplicantId() {
return applicantId;
}
public void setApplicantId(String applicantId) {
this.applicantId = applicantId;
}
public String getAttachmentId() {
return attachmentId;
}
public void setAttachmentId(String attachmentId) {
this.attachmentId = attachmentId;
}
@Override
public String toString() {
return "AttachmentBean{" +
"id='" + id + '\'' +
", applicantId='" + applicantId + '\'' +
", attachmentId='" + attachmentId + '\'' +
'}';
}
}
五 注意点
* 深度分页,页数过多时占用资源,使用scroll(有序)scroll-scan(无序);
* 提示不能以root用户启动
添加用户 xxx为你要添加的用户名
useradd xxx
给xxx用户设置密码
passwd xxx
输入密码
再次输入密码
给xxx用户权限,/ELK/elasticsearch-6.4.0是elasticsearch解压根目录
chown -R xxx /ELK/elasticsearch-6.4.0
切换用户为xxx
su xxx
再执行
./bin/elasticsearch
或者后台执行
nohup ./bin/elasticsearch >elasticsearch.out &
即可成功
————————————————
版权声明:本文为CSDN博主「King-Long」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011095110/article/details/82466299
* 公网访问
修改配置文件config/elasticsearch.yml network.host: 0.0.0.0
* 与springboot版本
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.requirements
* es映射类中可用@Field(type=FieldType.nested)嵌套对象,但嵌套对象不能直接操作,增删改需要将整个对象查出,修改后再整个存回去(覆盖回去)。至少2.x文档是这么说的。用put命令可以局部修改,但6.x的Script类参数大改,还没研究出怎么用,就先用了下述方法。
* es增删改
/*
* es cud通信示例
*/
@Transactional(propagation = Propagation.SUPPORTS)
public void saveQuestion2(QaQuestionES questionBean,String qaQuestionESId){
HashMap params = new HashMap();
params.put("questionDetail", JSON.toJSON(questionBean.getQuestionDetail()));
//6.x要用HashMap传参,不能用json。嵌套对象则将value对象转为json,基本类型直接放。
//修改用prepareUpdate,增加用prepareIndex。三个参数分别为映射类的索引、类型、主键。
elasticsearchTemplate.getClient().prepareUpdate(ESIndexName,ESTypeName,qaQuestionESId).setDoc(params).get();
}
//另一种通信方式
public void saveQuestion3(QaQuestionES.QuestionBean questionBean,String qaQuestionESId){
HashMap params = new HashMap();
UpdateRequest ur = new UpdateRequest();
ur.index(ESIndexName);
ur.type(ESTypeName);
ur.id(qaQuestionESId);
params.put("applicantTeam","四部");
ur.doc(params);
try {
elasticsearchTemplate.getClient().update(ur).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
* es查询
public QaQuestionES findByQuestionId(String id){
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//查询条件,嵌套对象下的条件则 父类属性名.字段名
QueryBuilder queryBuilder = QueryBuilders.matchQuery("questionId", id);
boolQueryBuilder.must(queryBuilder);
SearchResponse response = elasticsearchTemplate.getClient().prepareSearch("qa_question").setQuery(boolQueryBuilder).get();
// 返回搜索结果
SearchHits hits = response.getHits();
for (SearchHit searchHit : hits) {
try {
QaQuestionES qaQuestionES = objectMapper.readValue(searchHit.getSourceAsString(), QaQuestionES.class);
return qaQuestionES;
} catch (Exception e) {
log.error("结果解析异常{}", e);
}
}
return null;
}
* 注解
F 参考
https://my.oschina.net/wenjinglian/blog/1863361 增删改查方式介绍