分布式搜索引擎ElasticSearch——基礎(chǔ)

初識elasticsearch
什么是elasticsearch
elasticsearch的發(fā)展
https://lucene.apache.org/
https://www.elastic.co/cn/
正向索引和倒排索引
安裝elasticsearch,kibana
https://github.com/medcl/elasticsearch-analysis-ik
部署單點es
創(chuàng)建網(wǎng)絡(luò)
因為我們還需要部署kibana容器,因此需要讓es和kibana容器互聯(lián)。這里先創(chuàng)建一個網(wǎng)絡(luò):
docker network create es-net
加載鏡像
這里我們采用elasticsearch的7.12.1版本的鏡像,這個鏡像體積非常大,接近1G。不建議大家自己pull。網(wǎng)速沒問題的話,直接去pull也沒問題只要記得指定版本為7.12.1即可(學(xué)習(xí)教學(xué)方便)
課前資料提供了鏡像的tar包:
大家將其上傳到虛擬機中,然后運行命令加載即可:
# 導(dǎo)入數(shù)據(jù)
docker load -i es.tar
同理還有kibana
的tar包也需要這樣做。同理kibana也可以直接去pull
運行
運行docker命令,部署單點es:
docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
--network es-net \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:7.12.1
命令解釋:
-
-e "cluster.name=es-docker-cluster"
:設(shè)置集群名稱 -
-e "http.host=0.0.0.0"
:監(jiān)聽的地址,可以外網(wǎng)訪問 -
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
:內(nèi)存大小 -
-e "discovery.type=single-node"
:非集群模式 -
-v es-data:/usr/share/elasticsearch/data
:掛載邏輯卷,綁定es的數(shù)據(jù)目錄 -
-v es-logs:/usr/share/elasticsearch/logs
:掛載邏輯卷,綁定es的日志目錄 -
-v es-plugins:/usr/share/elasticsearch/plugins
:掛載邏輯卷,綁定es的插件目錄 -
--privileged
:授予邏輯卷訪問權(quán) -
--network es-net
:加入一個名為es-net的網(wǎng)絡(luò)中 -
-p 9200:9200
:端口映射配置
在瀏覽器中輸入:http://192.168.150.101:9200 即可看到elasticsearch的響應(yīng)結(jié)果:
部署kibana
kibana可以給我們提供一個elasticsearch的可視化界面,便于我們學(xué)習(xí)。
部署
運行docker命令,部署kibana
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
kibana:7.12.1
-
--network es-net
:加入一個名為es-net的網(wǎng)絡(luò)中,與elasticsearch在同一個網(wǎng)絡(luò)中 -
-e ELASTICSEARCH_HOSTS=http://es:9200"
:設(shè)置elasticsearch的地址,因為kibana已經(jīng)與elasticsearch在一個網(wǎng)絡(luò),因此可以用容器名直接訪問elasticsearch -
-p 5601:5601
:端口映射配置
kibana啟動一般比較慢,需要多等待一會,可以通過命令:
docker logs -f kibana
查看運行日志,當(dāng)查看到下面的日志,說明成功:
此時,在瀏覽器輸入地址訪問:http://192.168.150.101:5601,即可看到結(jié)果
DevTools
kibana中提供了一個DevTools界面:
安裝IK分詞器
在線安裝ik插件(較慢)
# 進入容器內(nèi)部
docker exec -it es /bin/bash
# 在線下載并安裝
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip
#退出
exit
#重啟容器
docker restart elasticsearch
離線安裝ik插件(推薦)
1)查看數(shù)據(jù)卷目錄
安裝插件需要知道elasticsearch的plugins目錄位置,而我們用了數(shù)據(jù)卷掛載,因此需要查看elasticsearch的數(shù)據(jù)卷目錄,通過下面命令查看:
docker volume inspect es-plugins
顯示結(jié)果:
[
{
"CreatedAt": "2022-05-06T10:06:34+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
"Name": "es-plugins",
"Options": null,
"Scope": "local"
}
]
說明plugins目錄被掛載到了:/var/lib/docker/volumes/es-plugins/_data
這個目錄中。
也就是/var/lib/docker/volumes/es-plugins/_data
:
4)重啟容器
# 4、重啟容器
docker restart es
# 查看es日志
docker logs -f es
5)測試:
IK分詞器包含兩種模式:
-
ik_smart
:最少切分 -
ik_max_word
:最細切分
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "黑馬程序員學(xué)習(xí)java太棒了"
}
結(jié)果:
{
"tokens" : [
{
"token" : "黑馬",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "程序員",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "程序",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "員",
"start_offset" : 4,
"end_offset" : 5,
"type" : "CN_CHAR",
"position" : 3
},
{
"token" : "學(xué)習(xí)",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "java",
"start_offset" : 7,
"end_offset" : 11,
"type" : "ENGLISH",
"position" : 5
},
{
"token" : "太棒了",
"start_offset" : 11,
"end_offset" : 14,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "太棒",
"start_offset" : 11,
"end_offset" : 13,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "了",
"start_offset" : 13,
"end_offset" : 14,
"type" : "CN_CHAR",
"position" : 8
}
]
}
擴展詞詞典
隨著互聯(lián)網(wǎng)的發(fā)展,“造詞運動”也越發(fā)的頻繁。出現(xiàn)了很多新的詞語,在原有的詞匯列表中并不存在。比如:“奧力給”,“傳智播客” 等。
所以我們的詞匯也需要不斷的更新,IK分詞器提供了擴展詞匯的功能。
1)打開IK分詞器config目錄:
2)在IKAnalyzer.cfg.xml配置文件內(nèi)容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴展配置</comment>
<!--用戶可以在這里配置自己的擴展字典 *** 添加擴展詞典-->
<entry key="ext_dict">ext.dic</entry>
</properties>
3)新建一個 ext.dic,可以參考config目錄下復(fù)制一個配置文件進行修改
傳智播客
奧力給
4)重啟elasticsearch
docker restart es
# 查看 日志
docker logs -f elasticsearch
日志中已經(jīng)成功加載ext.dic配置文件
5)測試效果:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "傳智播客Java就業(yè)超過90%,奧力給!"
}
注意當(dāng)前文件的編碼必須是 UTF-8 格式,嚴禁使用Windows記事本編輯
停用詞詞典
在互聯(lián)網(wǎng)項目中,在網(wǎng)絡(luò)間傳輸?shù)乃俣群芸欤院芏嗾Z言是不允許在網(wǎng)絡(luò)上傳遞的,如:關(guān)于宗教、政治等敏感詞語,那么我們在搜索時也應(yīng)該忽略當(dāng)前詞匯。
IK分詞器也提供了強大的停用詞功能,讓我們在索引時就直接忽略當(dāng)前的停用詞匯表中的內(nèi)容。
1)IKAnalyzer.cfg.xml配置文件內(nèi)容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴展配置</comment>
<!--用戶可以在這里配置自己的擴展字典-->
<entry key="ext_dict">ext.dic</entry>
<!--用戶可以在這里配置自己的擴展停止詞字典 *** 添加停用詞詞典-->
<entry key="ext_stopwords">stopword.dic</entry>
</properties>
3)在 stopword.dic 添加停用詞
停用詞
4)重啟elasticsearch
# 重啟服務(wù)
docker restart elasticsearch
docker restart kibana
# 查看 日志
docker logs -f elasticsearch
日志中已經(jīng)成功加載stopword.dic配置文件
5)測試效果:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "傳智播客Java就業(yè)率超過95%,停用詞都點贊,奧力給!"
}
注意當(dāng)前文件的編碼必須是 UTF-8 格式,嚴禁使用Windows記事本編輯
部署es集群
部署es集群可以直接使用docker-compose來完成,不過要求你的Linux虛擬機至少有4G的內(nèi)存空間
首先編寫一個docker-compose文件,內(nèi)容如下:
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
networks:
- elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
networks:
elastic:
driver: bridge
Run docker-compose
to bring up the cluster:
docker-compose up
索引庫操作
mapping屬性
創(chuàng)建索引庫
查詢,刪除索引庫
修改索引庫——添加字段
文檔操作
添加文檔
查看、刪除文檔
修改文檔
全量修改如果傳的id不存在,就直接成為新增了。
增量修改就是局部修改。
文檔操作——動態(tài)映射
RestClient操作索引庫
https://www.elastic.co/guide/en/elasticsearch/client/index.html
public class HotelIndexTest {
private RestHighLevelClient client;
@Test
void testInit(){
System.out.println(client);
}
// 創(chuàng)建索引庫
@Test
void createHotelIndex() throws IOException {
// 1. 創(chuàng)建request對象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2. 準備請求的參數(shù):DSL語句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3. 發(fā)送請求
client.indices().create(request, RequestOptions.DEFAULT);
}
// 刪除索引庫
@Test
void testDDeleteHotelIndex() throws IOException {
// 1. 創(chuàng)建Request對象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2. 發(fā)送請求
client.indices().delete(request,RequestOptions.DEFAULT);
}
// 判斷是否存在索引庫
@Test
void testExistsHotelIndex() throws IOException {
// 1. 創(chuàng)建Request對象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2. 發(fā)送請求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3. 輸出
System.out.println(exists ? "索引庫已經(jīng)存在": "索引庫不存在!");
}
@BeforeEach
void setUp(){
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.10.88:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
public class HotelConstants {
public static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"address\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"city\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"starName\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"location\": {\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"pic\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" \n" +
" }\n" +
"}";
}
RestClient操作文檔
@SpringBootTest
public class HotelDocumentTest {
private RestHighLevelClient client;
@Autowired
private IHotelService hotelService;
// 添加酒店數(shù)據(jù)到索引庫
@Test
void testAddDocument() throws IOException {
// 根據(jù)id查詢酒店數(shù)據(jù)
Hotel hotel = hotelService.getById(61083L);
// 轉(zhuǎn)換為文檔類型
HotelDoc hotelDoc = new HotelDoc(hotel);
// 1. 準備Request對象
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
// 2. 準備json文檔
request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
// 3. 發(fā)送文檔
client.index(request,RequestOptions.DEFAULT);
}
// 根據(jù)id查詢酒店數(shù)據(jù)
@Test
void testGetDocumentById() throws IOException {
// 1. 準備Request
GetRequest request = new GetRequest("hotel", "61083");
// 2. 發(fā)送請求,得到響應(yīng)
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3. 解析響應(yīng)結(jié)果
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
// 根據(jù)id修改酒店數(shù)據(jù)
@Test
void testUpdateDocument() throws IOException {
// 1. 準備request
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 2. 準備請求參數(shù)
request.doc(
"price", "998",
"starName", "四鉆"
);
// 3. 發(fā)送請求
client.update(request, RequestOptions.DEFAULT);
}
// 根據(jù)id刪除文檔數(shù)據(jù)
@Test
void testDeleteDocument() throws IOException {
// 1. 準備request
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2. 發(fā)送請求
client.delete(request, RequestOptions.DEFAULT);
}
@BeforeEach
void setUp(){
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.10.88:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
文章來源:http://www.zghlxwxcb.cn/news/detail-797949.html
利用JavaRestClient批量導(dǎo)入酒店數(shù)據(jù)到ES
文章來源地址http://www.zghlxwxcb.cn/news/detail-797949.html
// 批量添加
@Test
void testBulkRequest() throws IOException {
// 批量查詢酒店數(shù)據(jù)
List<Hotel> hotels = hotelService.list();
// 1. 創(chuàng)建Request
BulkRequest request = new BulkRequest();
// 2. 轉(zhuǎn)杯參數(shù),添加多個新增的Request
for (Hotel hotel : hotels) {
// 轉(zhuǎn)換為文檔類型HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel);
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc),XContentType.JSON));
}
// 3. 發(fā)送請求
client.bulk(request, RequestOptions.DEFAULT);
}
到了這里,關(guān)于分布式搜索引擎ElasticSearch——基礎(chǔ)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!