Elasticsearch的安裝和使用
下載Elasticsearch6.2.2的zip包砌溺,并解壓到指定目錄,下載地址:
https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
安裝中文分詞插件膏秫,在elasticsearch-6.2.2\bin目錄下執(zhí)行以下命令:
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
運(yùn)行bin目錄下的elasticsearch.bat啟動(dòng)Elasticsearch
下載Kibana,作為訪問(wèn)Elasticsearch的客戶端,請(qǐng)下載6.2.2版本的zip包做盅,并解壓到指定目錄缤削,下載地址:https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip
運(yùn)行bin目錄下的kibana.bat,啟動(dòng)Kibana的用戶界面
訪問(wèn)http://localhost:5601 即可打開Kibana的用戶界面
Get Put命令學(xué)習(xí)參考
https://www.xugj520.cn/archives/exploring_cluster.html
Springboot 整合Elasticsearch
版本參考
版本對(duì)應(yīng)很重要 我的是
springboot 2.1.3.RELEASE
es 6.2.2
spring data es 3.1.16.RELEASE
在pom.xml中添加相關(guān)依賴
<!--Elasticsearch相關(guān)依賴-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.1.16.RELEASE</version>
</dependency>
修改SpringBoot配置文件
修改application.yml文件吹榴,在spring節(jié)點(diǎn)下添加Elasticsearch相關(guān)配置亭敢。
# elasticsearch相關(guān)配置 .yml全局只能有一個(gè)spring注意
spring:
data:
elasticsearch:
cluster-name: elasticsearch # es集群的名稱
cluster-nodes: 127.0.0.1:9300 # 程序連接es的端口號(hào)是9300
Model
先寫一個(gè)的商品實(shí)體類,借助這個(gè)實(shí)體類來(lái)完成基礎(chǔ)的CRUD功能
package com.wg.biye.wgcore.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
//@Accessors @Data 是lombok的注解
//6.0版本以后图筹,一個(gè)index下帅刀,只允許創(chuàng)建一個(gè)type,不允許存在多個(gè)type 并且在官網(wǎng)提供信息远剩,7.0以后不再使用type劝篷。
@Data
@Accessors(chain = true)
@Document(indexName = "wgaituwang", type = "product",shards = 1,replicas = 0)//必須小寫
public class WgProduct implements Serializable {
/*
不需要中文分詞的字段設(shè)置成@Field(type = FieldType.Keyword)類型,需要中文分詞的設(shè)置成@Field(analyzer = "ik_max_word",type = FieldType.Text)類型民宿。
* */
private static final long serialVersionUID = -1L;
@Id
private String id;//必須添加@Id注解,最好為String類型
@Field(analyzer = "ik_max_word",type = FieldType.Text)//IK分詞器
private String name;//商品名稱
private String productAddress;//商品出產(chǎn)地
private String keywords;//商品關(guān)鍵字
@Field(analyzer = "ik_max_word",type = FieldType.Text)
private String title;//商品標(biāo)題
private Double price;//價(jià)格
// private String time;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date time;
/*
{
"id" : "1",
"name" : "火龍果",
"productAddress" : "北京天安門",
"keywords" : "水果",
"title" : "香甜可口的火龍果",
"price" : "100",
"time" : "2020-03-27"
}
*/
}
常用注解學(xué)習(xí)
@Document
屬性名 | 類型 | 含義 |
---|---|---|
indexName | String | 索引庫(kù)名字像鸡,相當(dāng)于mysql中數(shù)據(jù)庫(kù)的概念 |
type | String | 文檔類型活鹰,mysql中表的概念 |
shards | short | 默認(rèn)分片數(shù) 默認(rèn)值5 |
replicas | short | 默認(rèn)副本數(shù)量 默認(rèn)值1 |
@Id
可以認(rèn)為是mysql中表一行的Id概念
@Field
public @interface Field {
//文檔中字段的類型
FieldType type() default FieldType.Auto;
//是否建立倒排索引
boolean index() default true;
//是否進(jìn)行存儲(chǔ)
boolean store() default false;
//分詞器名次
String analyzer() default "";
}
其中字段類型的選項(xiàng)有
//為文檔自動(dòng)指定元數(shù)據(jù)類型
public enum FieldType {
Text,//會(huì)進(jìn)行分詞并建了索引的字符類型
Integer,
Long,
Date,
Float,
Double,
Boolean,
Object,
Auto,//自動(dòng)判斷字段類型
Nested,//嵌套對(duì)象類型
Ip,
Attachment,
Keyword//不會(huì)進(jìn)行分詞建立索引的類型
}
創(chuàng)建repository包
創(chuàng)建實(shí)體類的接口繼承ElasticsearchRepository這樣就有基本的CRUD(用過(guò)Jpa的就很清楚)
package com.wg.biye.wgcore.repository;
import com.wg.biye.wgcore.entity.WgProduct;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface WgProductRepository extends ElasticsearchRepository<WgProduct, String> {
}
我們就直接實(shí)現(xiàn)控制類吧
package com.wg.biye.wgcore.controller;
import com.wg.biye.common.util.ResultUtil;
import com.wg.biye.wgcore.entity.WgProduct;
import com.wg.biye.wgcore.repository.WgProductRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
//需要一個(gè)工具將MySQL的數(shù)據(jù)導(dǎo)入Elasticsearch
//@RestController = @Controller + @ResponseBody組成
@RestController
@RequestMapping("/wgproduct")
public class WgProductController {
@Autowired
private WgProductRepository wgProductRepository;
//@RequestBody學(xué)習(xí) : https://blog.csdn.net/justry_deng/article/details/80972817
@PostMapping("/add")
public Map<String, Object> add(@RequestBody WgProduct wgProduct) {
System.out.println(wgProduct.toString());
System.out.println(wgProduct instanceof WgProduct);//true
wgProductRepository.save(wgProduct);
return ResultUtil.resultCode(200,"添加商品成功"); ResultUtil工具換成自己的就行
}
//根據(jù)Id查詢
@GetMapping("/get/{id}")
public Map<String, Object> getById(@PathVariable String id) {
Map<String,Object> result = new HashMap<>();
if (StringUtils.isEmpty(id))
return ResultUtil.resultCode(500,"Id為空");
//【java8新特性】Optional詳解 http://www.reibang.com/p/d81a5f7c9c4e
Optional<WgProduct> wgProductOptional = wgProductRepository.findById(id);
if (wgProductOptional.isPresent()) {//isPresent()方法用于判斷包裝對(duì)象的值是否非空
WgProduct wgProduct = wgProductOptional.get();
result.put("商品信息",wgProduct);
return ResultUtil.resultSuccess(result);
}
return ResultUtil.resultError(result);
}
//查詢所有
@GetMapping("/getall")
public Map<String, Object> getAll() {
Map<String,Object> result = new HashMap<>();
Iterable<WgProduct> iterable = wgProductRepository.findAll();
List<WgProduct> list = new ArrayList<>();
iterable.forEach(list::add);
result.put("所有商品",list);
return ResultUtil.resultSuccess(result);
}
// 根據(jù)ID修改
@PostMapping("/update")
public Map<String, Object> updateById(@RequestBody WgProduct wgProduct) {
String id = wgProduct.getId();
if (StringUtils.isEmpty(id))
return ResultUtil.resultCode(500,"Id為空");
wgProductRepository.save(wgProduct);
return ResultUtil.resultCode(200,"修改商品成功");
}
// 根據(jù)ID刪除
@DeleteMapping("/delete/{id}")
public Map<String, Object> deleteById(@PathVariable String id) {
if (StringUtils.isEmpty(id))
return ResultUtil.resultCode(500,"Id為空");
wgProductRepository.deleteById(id);
return ResultUtil.resultCode(200,"刪除商品成功");
}
}
POSTMAN測(cè)試
增加
查看
刪除
搜索
構(gòu)造數(shù)據(jù) 在測(cè)試類胡亂寫
package com.wg.biye;
import com.wg.biye.wgcore.entity.*;
import com.wg.biye.wgcore.repository.WgProductRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class BiyeApplicationTests {
@Autowired
private WgProductRepository wgProductRepository;
@Test
public void contextLoads() {
WgProduct wgProduct = new WgProduct();
wgProduct.setId("100");
wgProduct.setTitle("好吃的");
wgProduct.setProductAddress("北京");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("水果");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("101");
wgProduct.setTitle("好玩的");
wgProduct.setProductAddress("成都");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("水果");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("102");
wgProduct.setTitle("好喝的");
wgProduct.setProductAddress("成都");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("飲料");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("103");
wgProduct.setTitle("好玩的");
wgProduct.setProductAddress("北京");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("玩具");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("104");
wgProduct.setTitle("好吃的");
wgProduct.setProductAddress("北京");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("水果");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("105");
wgProduct.setTitle("好吃的");
wgProduct.setProductAddress("成都");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("水果");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
wgProduct.setId("106");
wgProduct.setTitle("好吃的");
wgProduct.setProductAddress("北京");
wgProduct.setPrice(20.0);
wgProduct.setTime(new Date());
wgProduct.setKeywords("水果");
wgProduct.setName("梨");
wgProductRepository.save(wgProduct);
}
}
查詢所有數(shù)據(jù)
搜索標(biāo)題中以關(guān)鍵字開頭的方法
WgProductRepository.class添加方法
List<WgProduct> findAllByTitleLike(String s);
控制器添加
@GetMapping("/search/title")
public Map<String, Object> repSearchTitle(String keyword) {
if (StringUtils.isEmpty(keyword))
return ResultUtil.resultCode(500,"條件為空");
Map<String,Object> result = new HashMap<>();
List<WgProduct> list = new ArrayList<>();
list = wgProductRepository.findAByTitleLike(keyword);
result.put("搜索結(jié)果",list);
return ResultUtil.resultSuccess(result);
}
搜索結(jié)果
{
"code": 200,
"搜索結(jié)果": [
{
"id": "100",
"name": "梨",
"productAddress": "北京",
"keywords": "水果",
"title": "好吃的",
"price": 20.0,
"time": "2020-03-27"
},
{
"id": "104",
"name": "梨",
"productAddress": "北京",
"keywords": "水果",
"title": "好吃的",
"price": 20.0,
"time": "2020-03-27"
},
{
"id": "105",
"name": "梨",
"productAddress": "成都",
"keywords": "水果",
"title": "好吃的",
"price": 20.0,
"time": "2020-03-27"
},
{
"id": "106",
"name": "梨",
"productAddress": "北京",
"keywords": "水果",
"title": "好吃的",
"price": 20.0,
"time": "2020-03-27"
}
],
"message": "操作成功"
}
更多API請(qǐng)參考