springboot+elasticsearch+kibana整合本地搭建环境
springboot+elasticsearch+kibana整合本地搭建环境
准备
下载软件
elasticsearch-5.5.1
kibana-5.5.1
elasticsearch-analysis-ik-5.5.1
springboot 2.0.4.RELEASE
注意
版本必须是对应上的
1.下面是Springboot,Spring Data Elasticsearch,Elasticsearch的版本对应
2.elasticsearch ,kibana ,elasticsearch-analysis-ik 必须版本一致
安装 elasticsearch kibana
1.解压elasticsearch , kibana 到 D:\ELK目录
2.修改配置文件
** elasticsearch** :D:\ELK\elasticsearch-5.5.1\config\elasticsearch.yml
//主机地址
network.host: 192.168.63.248
#network.hostbind_host: 192.168.63.248
#network.publish_host: 192.168.63.248
//http的端口
http.port: 9200
//服务通信的端口
transport.tcp.port: 9300
//集群名称
cluster.name: es_cluster_lmq
//节点名称
node.name: node-lmq-1
** kibana** : D:\ELK\kibana-5.5.1-windows-x86\config\kibana.yml
//端口
server.port: 5601
//主机地址
server.host: "192.168.63.248"
//es的http的地址
elasticsearch.url: "http://192.168.63.248:9200/"
- 启动
启动es:D:\ELK\elasticsearch-5.5.1\bin\elasticsearch.bat,完成后 打开es的http地址,就能看到es一下信息,集群名,版本等 http://192.168.63.248:9200/
再启动 kibana,es没启动,直接启动kibana会报错 http://192.168.63.248:5601
这样就算是 es和kibana搭建成功了
中文分词查询
es的默认分词器
首先说个例子
我要查询数据中 shortTitle包含 “旗舰店” 的数据,
1.那我就用模糊查询 wildcard , “shortTitle”:“旗舰店” 通配符查询,查询没有数据 图1
2.那我换个方式: “shortTitle.keyword”:"*旗舰店" ,就有数据了
这个原因是因为 shopTitle 是text的类型 是走分词,倒排索引的, shopTitle.keyword的类型需要全字段的精确匹配,
全文匹配不用说了, 字符串:“官网旗舰店” 用通配符查询,肯定是查询到数据的
text的类型的话,是会分词,查询的时候就检索分词后的每个词条,es的默认分词 是分成一个一个词,作为索引,这样的话,我拿 “旗舰店” 去匹配查询 一个一个词 肯定是查不到的
ik中文分词器
上面准备工作已经下载下来了
引入到es
1.D:\ELK\elasticsearch-5.5.1\plugins 新建文件夹 ik
2.解压ik,把文件复制到 ik文件夹下面
重启es
控制台能看到 已加载了 ik了
ik分词器提供了两个模式的分词 ik_max_word(会将文本做最细粒度的拆分) ik_smart (会做最粗粒度的拆分) 分别看下分词效果 看到分词效果好很多了
再来模糊查询看看 ,因为我配置的 title字段是根据ik中文分词器,这样就能 根据分词后的 字条“旗舰店” 查询到了
有了中文分词的话 ,我们用的查询就用 match ,match 是先把查询的字符串进行分词(要自定义映射文件),然后再去查询分词索引的, 例如 是查询 “官网旗舰店” 分词后是 官, 网, 旗舰店,这样就能查询到,这些数据
,,只要包含了就能查询出来,
那我想查询 包含 网, 旗舰店,的数据呢,“operator”: “and” 就行了 就只会有一条数据
也可以查询看下一条数据单个字段的分词情况
get /ricer_shop_tbk_item/ricer_shop_tbk_item/580332176701/_termvectors?fields=shortTitle
get /indexName/indexType/数据的主键ID/_termvectors?fields=需要查询字段的 可以看到就是一个词一个词分的
get /ricer_shop_tbk_item/ricer_shop_tbk_item/580332176701/_termvectors?fields=title
title是配置了ik中文分词的 这样看来分词效果还不错
springboot+elasticsearch整合
引入jar包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置es服务地址 这里用的就是 9300 端口
data:
elasticsearch:
cluster-name: es_cluster_lmq
cluster-nodes: 192.168.63.248:9300
创建索引 通过注解配置
@Autowired
private ItemRepository itemRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
public void initESItem() {
//删除索引
elasticsearchTemplate.deleteIndex(ESTbkItem.class);
//创建索引
elasticsearchTemplate.createIndex(ESTbkItem.class);
//加载动态映射
elasticsearchTemplate.putMapping(ESTbkItem.class);
}
@Data
@NoArgsConstructor
@Accessors(chain = true)
@Mapping(mappingPath = "mapping/tbk_item_mapping.json")//配置自定义的映射文件
@Document(indexName = "ricer_shop_tbk_item", type = "ricer_shop_tbk_item",shards = 1,replicas = 0)
public class ESTbkItem implements Serializable {
@Id
private Long itemId;
private Long categoryId;
private String categoryName;
}
创建好了就能在kibana上查询索引的信息 es自身也是可以查询的http://192.168.63.248:9200/_mapping/ricer_shop_tbk_item
我这操作es的数据的话 是通过 ElasticsearchRepository 来操作的
//添加数据如下 (增删改 jpa都一样的)
List<ESTbkItem> esTbkItems = Lists.newArrayList();
itemRepository.saveAll(esTbkItems);
//下面说下查询
public Page<ESTbkItem> findByParams(Map<String, Object> param) {
log.info("findByParams:" + JSONObject.toJSONString(param));
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//排序
Sort sort = sortBuilder(param.get("orderByColumn") == null ? "":param.get("orderByColumn").toString());
//分页
Pageable pageable = PageRequest.of(Integer.valueOf(param.get("pageNo").toString()) - 1, Integer.valueOf(param.get("pageSize").toString()), sort);
queryBuilder.withPageable(pageable);
//
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (Objects.nonNull(param.get("itemName"))) {
//添加ik分词插件 分词查询
// boolQueryBuilder.must(QueryBuilders.matchQuery("title", param.get("itemName"));
//不进行分词,模糊查询
boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("title", param.get("itemName")));
}
if (Objects.nonNull(param.get("category"))) {
//精确查询
boolQueryBuilder.must(QueryBuilders.termQuery("categoryId", param.get("category")));
}
// in
if (Objects.nonNull(param.get("categorys"))) {
List<Long> categorys = (List<Long>) param.get("categorys");
boolQueryBuilder.must(QueryBuilders.termsQuery("categoryId", categorys));
}
// 大于
if (Objects.nonNull(param.get("couponUsedRateStart"))) {
boolQueryBuilder.must(QueryBuilders.rangeQuery("couponUsedRate").gt(param.get("couponUsedRateStart")));
}
// 小于
if (Objects.nonNull(param.get("couponUsedRateEnd"))) {
boolQueryBuilder.must(QueryBuilders.rangeQuery("couponUsedRate").lt(param.get("couponUsedRateEnd")));
}
queryBuilder.withQuery(boolQueryBuilder);
return itemRepository.search(queryBuilder.build());
}
//构建 orderby
private Sort sortBuilder(String orderByColumn) {
List<Sort.Order> list = Lists.newArrayList();
if (Objects.isNull(orderByColumn)) {
//默认排序字段
Sort.Order order = new Sort.Order(Sort.Direction.DESC, "volume");
list.add(order);
} else {
//多字段排序 "price:desc,volume:asc"
String[] orderByColumn_arr = orderByColumn.split(",");
for (String s : orderByColumn_arr) {
String[] colum_arr = s.split(":");
if (colum_arr.length == 2) {
Sort.Order order = new Sort.Order(colum_arr[1].equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESC, colum_arr[0]);
list.add(order);
}
}
}
Sort sort = new Sort(list);
return sort;
}
springboot+ ik中文分词器
自定义映射文件 ps:如果改过映射文件,需要删除索引 ,重新加载,不然不会生效的
{
"properties": {
//可以只对单个的字段进行配置,未配置的字段是默认配置的
"title": {//配置字段 title
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"analyzer": "ik_max_word",//查询数据是 按照最细的分词
"search_analyzer": "ik_smart"//查询数据时,按照最粗的来分词
}
}
}
get ricer_shop_tbk_item/_mapping 可以看到映射文件已经生效了
ElasticsearchTemplate 查询实现查询结果高亮显示
上代码
Integer pageSize = 10;
Integer pageNo = 1;
Pageable pageable = PageRequest.of(pageNo - 1, pageSize);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withPageable(pageable);
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
if (StringUtils.isNotEmpty(textLike)) {
boolQueryBuilder.must(matchQuery("title", textLike).operator(Operator.AND));//分词后,查询结果是并且的意思,例如 查询 培根汉堡 ,查询处理的数据中,是包含 培根+汉堡的,需要查询或者的话就是 就是Operator.OR
nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"));//标记title查询结果需要高亮, <em> </em> 是匹配出来的词前后的标签,自定义替换的
}
SortOrder sortOrder = SortOrder.DESC;
//排序
FieldSortBuilder fieldSortBuilder = new FieldSortBuilder("reservePrice");
fieldSortBuilder.order(sortOrder);
nativeSearchQueryBuilder.withSort(fieldSortBuilder);
nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
nativeSearchQueryBuilder.withIndices("ricer_shop_tbk_item");//indexName
Page<ESTbkItem> shops = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), ESTbkItem.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<ESTbkItem> chunk = Lists.newArrayList();
if (response.getHits().getHits().length > 0) {
for (SearchHit searchHit : response.getHits()) {
ESTbkItem item = JSON.parseObject(searchHit.getSourceAsString(), ESTbkItem.class);
if (MapUtils.isNotEmpty(searchHit.getHighlightFields())) {
HighlightField title = searchHit.getHighlightFields().get("title");
if (title != null) {
item.setTitle(title.fragments()[0].toString());//替换成高亮的结果
System.out.println(title.fragments()[0].toString());
}
}
chunk.add(item);
}
}
return new AggregatedPageImpl<>((List<T>) chunk, pageable, response.getHits().totalHits);
}
});
查询数量的结果就是这样的 ,这样就更加直观看的出,查询的时候名字的哪些词
扩展
1.有个场景 我查询“打底衫”,ik的分词是 “打底” “衫” ,但是我只想查询关于打底衫的数据, ik也是支持自定义的分词词库的,只需要把我们自定义的分词词库导入到ik插件里面就行了,方法如下:
还没深入研究。。。另外查资料了解吧
es也是前段时间项目里面用到了,就自己搭建了了解了一下, 最近需要用到分词, 所以又查各种资料,然后就想着干脆记录一下,免的忘记了,
本人对es也是入门级的, 有错误的的地方,还请见谅,可以指出,我及时修改