安裝ElasticSearch
- 安裝1.8及以上的jdk
- https://www.elastic.co/cn/downloads/elasticsearch 下載對應(yīng)版本
- 上傳到云服務(wù)器 /usr/local/software/ 目錄下
- tar -zxvf elasticsearch-7.12.1-linux-x86_64.tar.gz解壓
- cd /usr/local/software/elasticsearch-7.12.1/bin
- 執(zhí)行./elasticsearch報錯
java.lang.RuntimeException: can not run elasticsearch as root
- 新建es用戶
- cd /usr/local/software
- groupadd esgroup
- useradd esuser -g esgroup -p 123456
- chown -R esuser:esgroup elasticsearch-7.12.1/
- su - esuser
- ./elasticsearch 前臺啟動
- ./elasticsearch -d 后臺啟動 需要等一段時間
- 配置跨域訪問 /usr/local/software/elasticsearch-7.12.1/config/elasticsearch.yml 最后添加下面兩行
http.cors.enabled: true
http.cors.allow-origin: "*"
curl 127.0.0.1:9200 成功會有相應(yīng)信息
如果出現(xiàn) max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]錯誤 編輯 /etc/sysctl.conf,追加以下內(nèi)容:vm.max_map_count=655360保存后建丧,執(zhí)行:sysctl -p
-
出現(xiàn) max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536] 切換到root用戶編輯 /etc/security/limits.conf,追加以下內(nèi)容
soft nofile 65536 hard nofile 65536
默認(rèn)只允許本機訪問 配合Nginx 實現(xiàn)外網(wǎng)訪問
upstream es_pool{
server 127.0.0.1:9200;
}
upstream es_header_pool{
server 127.0.0.1:9100;
}
server {
listen 80;
server_name localhost;
location /es/ {
proxy_pass http://es_pool/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /es_header/ {
proxy_pass http://es_header_pool/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
- 允許內(nèi)網(wǎng)訪問的 elasticsearch.yml 配置文件
cluster.name: my-application
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: ["node-1"]
http.cors.allow-origin: "*"
http.cors.enabled: true
http.cors.allow-headers : X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization
http.cors.allow-credentials: true
安裝ElasticSearch-Head
通過https://nodejs.org/en/download/ 下載nodejs版本
上傳到/usr/local/software下面
tar -xvf node-v14.17.0-linux-x64.tar.xz 解壓
export PATH=$PATH:/usr/local/software/node-v14.17.0-linux-x64/bin
ln -s /usr/local/software/node-v14.17.0-linux-x64/bin/npm /usr/local/bin/
ln -s /usr/local/software/node-v14.17.0-linux-x64/bin/node /usr/local/bin/執(zhí)行node -v 打印版本 成功
yum install -y unzip zip 安裝unzip解壓
上傳到/usr/local/software/ unzip elasticsearch-head-master.zip
npm install -g grunt-cli 安裝依賴
yum install bzip2 //可能會報解壓錯誤 沒有忽略即可
npm install cnpm -g --registry=https://registry.npm.taobao.org 使用npm因為網(wǎng)絡(luò)原因總是報錯
cd elasticsearch-head-master/ 執(zhí)行 cnpm install
修改Gruntfile.js
connect: {
server: {
options: {
hostname: '*', # 添加這一行
port: 9100,
base: '.',
keepalive: true
}
}
}
- 修改_site下面的app.js 4388行左右將localhost替換成ElasticSearch的服務(wù)器地址
this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://192.168.0.199:9200";
- npm run start 啟動
- nohup npm run start & 后臺啟動
安裝 Kibana
- https://www.elastic.co/cn/downloads/kibana 下載 版本一定要和ElasticSearch一致
- 上傳到服務(wù)器 /usr/local/software 并解壓
- cd /usr/local/software
- mv kibana-7.12.1-linux-x86_64/ kibana
server.host: "192.168.0.199"
elasticsearch.hosts: ["http://192.168.0.199:9200"]
i18n.locale: "zh-CN"
- 執(zhí)行bin目錄下的kibana ./kibana --allow-root
- 訪問 http://192.168.0.199:5601/
ElasticSearch 術(shù)語
- 索引index —— 擁有相似文檔的集合
- 類型type —— 一個索引中可以定義多個類型
- 字段field —— 相當(dāng)于數(shù)據(jù)庫表中的字段
- 映射mapping —— 處理數(shù)據(jù)方式和規(guī)格方面做一些限制
- 文檔document —— 一個文檔是一個可被索引的基礎(chǔ)單元
- 分片 —— 由于單臺機器無法存儲大量數(shù)據(jù)波势,ES 可以將一個索引中的數(shù)據(jù)切分為多個分片(Shard)翎朱,分布在多臺服務(wù)器上存儲。
- 復(fù)制 —— 備份
操作
- 使用PUT請求添加text索引 http://192.168.0.199/es/test
- 新建索引的時候設(shè)置mapping信息 注意 7.4 默認(rèn)不在支持指定索引類型 http://192.168.0.199/es/test1 下面是請求體
{
"mappings": {
"properties": {
"id": {
"type": "long",
"store": true
},
"title": {
"type": "text",
"store": true,
"analyzer": "standard"
},
"content": {
"type": "text",
"store": true,
"analyzer": "standard"
}
}
}
}
- 查看索引對應(yīng)的映射 類型默認(rèn)都是_doc
{
"mappings": {
"_doc": {
"properties": {
"content": {
"type": "text",
"store": true,
"analyzer": "standard"
},
"id": {
"type": "long",
"store": true
},
"title": {
"type": "text",
"store": true,
"analyzer": "standard"
}
}
}
}
}
- 索引創(chuàng)建完成后POST請求添加mapping信息 http://192.168.0.199/es/test/db1/_mapping?include_type_name=true 在test下面新增db1結(jié)果如下
{
"mappings": {
"db1": {
"properties": {
"content": {
"type": "text",
"store": true,
"analyzer": "standard"
},
"id": {
"type": "long",
"store": true
},
"title": {
"type": "text",
"store": true,
"analyzer": "standard"
}
}
}
}
}
- DELETE請求刪除索引庫 http://192.168.0.199/es/test1
- 添加文檔(一條數(shù)據(jù)就是一個文檔)http://192.168.0.199/es/test/db1/1 在db1類型下設(shè)置id為1的數(shù)據(jù) 下面是請求體 保持和映射一致就行 如果db1后面不加/1 會自動生成一個隨機字符串id 操作時一般保持id字段和請求體里面的id字段保持一致
{
"id":1,
"title":"文檔標(biāo)題",
"content":"文檔內(nèi)容"
}
id設(shè)置相同數(shù)據(jù)會被覆蓋 用來實現(xiàn)修改文檔
DELETE方法刪除文檔 http://192.168.0.199/es/test/db1/1
-
查詢
根據(jù)id查詢 GET請求 http://192.168.0.199/es/test/db1/1 即可
-
關(guān)鍵字 POST http://192.168.0.199/es/test/db1/_search 只能使用一個漢字
{ "query":{ "term":{ "title":"文" //在title字段上查詢關(guān)鍵字有文的 } } }
queryString查詢 路徑同上
{ "query_string":{ "term":{ "default_field":"title", "query":"文檔" } } }
- 先分詞 如果title中包含文 或者 檔 的都會被查出來
- 查看分詞情況 GET 請求 http://192.168.0.199/es/test/_analyze
{ "analyzer" : "standard", "text": ["文檔標(biāo)題2"] }
- 關(guān)鍵詞查詢 like query_string 先對查詢內(nèi)容分詞
{ "query":{ "query_string":{ "query":"title:(\"題2\")", "default_operator": "and" } } }
or
{ "query": { "match_phrase": { "title": "題2" } } }
安裝中文分詞器IK
ElasticSearch內(nèi)置分詞器
- standard分詞器:(默認(rèn)分詞器)它會將詞匯單元轉(zhuǎn)換成小寫形式尺铣,并除去停用詞(a拴曲、an、the等)和標(biāo)點符號凛忿,支持中文采用的方法為單字切分澈灼。
- simple分詞器:首先會通過非字母字符來分割文本信息,然后將詞匯單元統(tǒng)一成小寫形式店溢,該分詞器會去掉數(shù)據(jù)類型的字符叁熔。
- Whitespace分詞器:僅僅是去掉空格,對字符沒有l(wèi)owcase化床牧,不支持中文荣回;并且不對生成的詞匯單元進(jìn)行其他的標(biāo)準(zhǔn)化處理。
- language分詞器:特定語言的分詞器戈咳,不支持中文
中文分詞器的安裝
- https://github.com/medcl/elasticsearch-analysis-ik/releases 下載最新版本的zip包
- cd /usr/local/software/elasticsearch-7.12.1/plugins/
- mkdir ik
- 把文件移動到ik目錄下
- cd ik/
- unzip elasticsearch-analysis-ik-7.12.1.zip
- 切換用戶重啟 elasticsearch
- 新建映射的時候就需使用ik分析器
- ik_smart(最行娜怼) 和 ik_max_word(最細(xì))的區(qū)別 舉例分析程序員 ik_smart 會解析成程序員 ik_max_word 會解析成三個分別是 程序員 程序 員
{
"mappings": {
"db1": {
"properties": {
"content": {
"type": "text",
"store": true,
"analyzer": "ik_smart"
},
"id": {
"type": "long",
"store": true
},
"title": {
"type": "text",
"store": true,
"analyzer": "ik_max_word"
}
}
}
}
}
集群
修改config\elasticsearch.yml文件添加
#集群名稱壕吹,保證唯一
cluster.name: my‐elasticsearch
#節(jié)點名稱,必須不一樣
node.name: node‐1 # node‐2 node‐3
#必須為本機的ip地址
network.host: 192.168.0.199 # 0.200 0.201
#服務(wù)端口號
http.port: 9200
#服務(wù)TCP端口號
transport.tcp.port: 9300
#設(shè)置集群自動發(fā)現(xiàn)機器ip集合
discovery.zen.ping.unicast.hosts:["192.168.0.199:9300","192.168.0.200:9300","192.168.0.201:9302"]
SpringBoot 整合
- 創(chuàng)建工程 并引入依賴 內(nèi)部引用的es版本必須要和服務(wù)器安裝的匹配
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- application.yml配置
spring:
elasticsearch:
rest:
uris: 192.168.0.199:9200
username: my-application
# uris:192.168.0.199:9200,192.168.0.200:9200,192.168.0.201:9200,
- 實體與document對應(yīng)類
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
@Document(indexName = "stu") //索引名稱
@Data
public class Stu {
@Id
private Long stuId; //會創(chuàng)建相同的文檔id 否則自動生成
@Field(store = true)
private String name;
@Field(store = true)
private Integer age;
}
- 實體類中新加四個字段 會自動添加到索引里面
@Field(store = true)
private Float money;
@Field(store = true, type = FieldType.Keyword)
private String sign;
@Field(store = true)
private String description;
@Field(type = FieldType.Date, format = DateFormat.date_time)
private Date recordTime;
- 關(guān)于常用方法 2.3.10 版本中的
@RunWith(SpringRunner.class)
@SpringBootTest
public class ESTest {
/**
* 一般不建議用Spring來創(chuàng)建/更新 刪除索引
* 一般針對文檔進(jìn)行CRUD操作
*/
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 創(chuàng)建/更新索引 如果存在 就更新 不會再創(chuàng)建 一般不使用
*/
@Test
public void createIndexStu() {
Stu stu = new Stu();
stu.setStuId(1006L);
stu.setAge(33);
stu.setName("李七");
stu.setRecordTime(new Date());
IndexQuery indexQuery = new IndexQueryBuilder().withObject(stu).build();
IndexCoordinates indexCoordinates = elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class);
elasticsearchRestTemplate.index(indexQuery, indexCoordinates);
}
/**
* 更新文檔
*/
@Test
public void updateStuDoc() {
Document document = Document.create();
document.put("name", "李四");
document.put("age", 20);
UpdateQuery updateQuery = UpdateQuery.builder("1000").withDocument(document).build();
elasticsearchRestTemplate.update(updateQuery, elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class));
}
/**
* 查詢 + 高亮顯示
*/
@Test
public void queryStuDoc() {
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//必須滿足的條件 加keyword不會拆分 不加會拆分成李和四
// boolQueryBuilder.must().add(new TermQueryBuilder("name.keyword", "李四"));
// boolQueryBuilder.must().add(new TermQueryBuilder("name", "四"));
// 查詢3天內(nèi)數(shù)的數(shù)據(jù)
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("recordTime");
rangeQueryBuilder.gte(LocalDateTime.now().minusDays(3));
// 或者下面的
// rangeQueryBuilder
// .from("2021-05-16T00:00:00.000Z")
// .to("2021-05-19T23:59:59.000Z");
// boolQueryBuilder.must().add(rangeQueryBuilder);
// 分頁查詢20條
PageRequest pageRequest = PageRequest.of(0, 20, Sort.by("stuId").descending());
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder
.withQuery(boolQueryBuilder)
// 親測使用.keyword有值但是高亮數(shù)據(jù)size = 0
.withHighlightBuilder(new HighlightBuilder().field("name")
.preTags("<font color='red'>")
.postTags("</font>"))
.withPageable(pageRequest);
Query searchQuery = searchQueryBuilder.build();
SearchHits<Stu> result = elasticsearchRestTemplate.search(searchQuery, Stu.class);
List<SearchHit<Stu>> hitList = result.getSearchHits();
System.out.println("hit size -> {}" + hitList.size());
hitList.forEach(hit -> {
Map<String, List<String>> highlightFields = hit.getHighlightFields();
List<String> nameHighlight = highlightFields.get("name");
if (nameHighlight != null) {
for (String text : nameHighlight) {
hit.getContent().setName(text);
}
}
System.out.println("返回數(shù)據(jù):" + hit.getContent().toString());
});
}
/**
* 刪除文檔
*/
@Test
public void delIndexDoc() {
elasticsearchRestTemplate.delete("1000", elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class));
}
}