Elasticsearch使用指南
- Create by yster@foxmail.com 2018-7-1
- 官方文檔:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
- 23個頗有用的查詢示例:https://www.coyee.com/article/10764-23-useful-elasticsearch-example-queries/
前言
ES是什麼
ElasticSearch簡寫ES,ES是一個高擴展、開源的全文檢索和分析引擎,它能夠準實時地快速存儲、搜索、分析海量的數據。javascript
什麼是全文檢索
全文檢索是指計算機索引程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先創建的索引進行查找,並將查找的結果反饋給用戶的檢索方式。這個過程相似於經過字典中的檢索字表查字的過程。全文搜索搜索引擎數據庫中的數據。php
ES的應用場景
- 一個線上商城系統,用戶須要搜索商城上的商品。
在這裏你能夠用ES存儲全部的商品信息和庫存信息,用戶只須要輸入」空調」就能夠搜索到他須要搜索到的商品。 - 一個運行的系統須要收集日誌,用這些日誌來分析、挖掘從而獲取系統業務將來的趨勢。
你能夠用logstash(elk中的一個產品,elasticsearch/logstash/kibana)收集、轉換你的日誌,並將他們存儲到ES中。一旦數據到達ES中,就你能夠在裏面搜索、運行聚合函數等操做來挖掘任何你感興趣的信息。 - 若是你有想基於大量數據(數百萬甚至數十億的數據)快速調查、分析而且要將分析結果可視化的需求。
你能夠用ES來存儲你的數據,用kibana構建自定義的可視化圖形、報表,爲業務決策提供科學的數據依據。
直白點講,ES是一個企業級海量數據的搜索引擎,能夠理解爲是一個企業級的百度搜索,除了搜索以外,ES還能夠快速的實現聚合運算。css
ES的存儲結構
ES存儲結構與MYSQL具備以下對應關係:html
ES | MYSQLjava |
索引 | 數據庫 |
類型 | 數據表 |
文檔 | 數據表的一行 |
屬性 | 數據表的一列 |
第一章:安裝
環境:node
Centos7.4系統nginx
Putty遠程鏈接git
1.下載
下載地址去官網啥的複製下來github
wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.4.1/elasticsearch-2.4.1.tar.gz
2.解壓
新手注意下執行目錄不要錯web
tar -zxvf elasticsearch-2.4.1.tar.gz
3.配置
找到解壓後的config文件夾打開elasticsearch.yml
下面貼出個人設置
關鍵是要打開network.host: 0.0.0.0
和http.port: 9200
註釋,提供web訪問
# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
# Before you set out to tweak and tune the configuration, make sure you
# understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please see the documentation for further information on configuration options:
# <http://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration.html>
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 集羣名稱,默認爲elasticsearch
cluster.name: my-application
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 節點名稱,es啓動時會自動建立節點名稱,但你也可進行配置
node.name: node-1
#
# Add custom attributes to the node:
#
# 是否做爲主節點,每一個節點均可以被配置成爲主節點,默認值爲true:
# node.master: true
#
# node.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
# 分配給當前節點的索引數據所在的位置
# path.data: /path/to/data
#
# Path to log files:
# 日誌文件所在位置
# path.logs: /path/to/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
# bootstrap.memory_lock: true
#
# Make sure that the `ES_HEAP_SIZE` environment variable is set to about half the memory
# available on the system and that the owner of the process is allowed to use this limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, see the documentation at:
# <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html>
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when new node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
# discovery.zen.ping.unicast.hosts: ["host1", "host2"]
#
# Prevent the "split brain" by configuring the majority of nodes (total number of nodes / 2 + 1):
#
# discovery.zen.minimum_master_nodes: 3
#
# For more information, see the documentation at:
# <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html>
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
# gateway.recover_after_nodes: 3
#
# For more information, see the documentation at:
# <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-gateway.html>
#
# ---------------------------------- Various -----------------------------------
#
# Disable starting multiple nodes on a single system:
#
# node.max_local_storage_nodes: 1
#
# Require explicit names when deleting indices:
#
# action.destructive_requires_name: true
4.啓動
在bin目錄下執行命令
1.規範的方式
./elasticsearch -d
2.通用的方式(注意&的語法是爲了讓程序後臺執行,當你Ctrl
+C
退出時程序依舊運行)
./elasticsearch &
這裏應該會報錯,提示不能使用root用戶啓動該服務。
而後你能夠新建一個用戶admin,並設置elasticsearch解壓後的全部文件權限爲777,命令行:
useradd admin
chmod -R 777 elasticsearch
su admin
./elasticsearch -d
5.查看內存
執行命令
ps -ef|grep elasticsearch
能夠看到在內存爲2G的主機上,Elasticsearch的運行內存爲 -Xms256m -Xmx1g
7.內存優化
1.最簡單的一個方法就是指定ES_HEAP_SIZE環境變量。服務進程在啓動時候會讀取這個變量,並相應的設置堆的大小。設置命令以下:
export ES_HEAP_SIZE=1g
2.咱們能夠在啓動程序時限制內存大小,不過這個方法並非每一個狀況均可以成功的,命令行以下
./elasticsearch -Xms256m -Xmx256m -d
備註: 確保Xmx和Xms的大小是相同的,其目的是爲了可以在java垃圾回收機制清理完堆區後不須要從新分隔計算堆區的大小而浪費資源,能夠減輕伸縮堆大小帶來的壓力。 通常來講設置ES_HEAP_SIZE環境變量,比直接寫-Xmx10g -Xms10g更好一點。
6.訪問網頁
由於開啓了http訪問,並設置能夠遠程鏈接,因此咱們直接請求網址便可:
http://你的服務器IP:9200
網頁響應內容
{
"name": "node-1",
"cluster_name": "my-application",
"cluster_uuid": "zrghL-WiQzeVE4rlX0WUAg",
"version": { "number": "2.4.1", "build_hash": "c67dc32e24162035d18d6fe1e952c4cbcbe79d16", "build_timestamp": "2016-09-27T18:57:55Z", "build_snapshot": false, "lucene_version": "5.5.2" },
"tagline": "You Know, for Search" }
安裝成功!
7.可視化插件
利用在bin目錄下提供的plugin插件安裝head,實現web可視化
注意目錄:
./bin/plugin install mobz/elasticsearch-head
安裝完後訪問
http://你的服務器IP:9200/_plugin/head/
出現
第二章:查詢
1.多索引
Elasticsearch容許咱們搜索存在於全部索引或一些特定索引中的文檔。 例如,若是咱們須要搜索名稱包含central
的全部文檔。注意此時的URL無索引
GET http://localhost:9200/_search?q = name:central
響應
{
"took": 78,
"timed_out": false,
"_shards": { "total": 10, "successful": 10, "failed": 0 },
"hits": { "total": 1, "max_score": 0.19178301, "hits": [ { "_index": "schools", "_type": "school", "_id": "1", "_score": 0.19178301, "_source": { "name": "Central School", "description": "CBSE Affiliation", "street": "Nagan", "city": "paprola", "state": "HP", "zip": "176115", "location": [ 31.8955385, 76.8380405 ], "fees": 2000, "tags": [ "Senior Secondary", "beautiful campus" ], "rating": "3.5" } } ] } }
或者,一樣地咱們能夠在schools
,schools_gov
索引中搜索 -
2.多類型
還能夠在全部類型或某種指定類型的索引中搜索全部文檔。 例如,注意此時的URL無類型
Get http://localhost:9200/schools/_search?q = tags:sports
響應
{
"took": 16,
"timed_out": false,
"_shards": { "total": 5, "successful": 5, "failed": 0 },
"hits": { "total": 1, "max_score": 0.5, "hits": [ { "_index": "schools", "_type": "school", "_id": "2", "_score": 0.5, "_source": { "name": "Saint Paul School", "description": "ICSE Afiliation", "street": "Dawarka", "city": "Delhi", "state": "Delhi", "zip": "110075", "location": [ 28.5733056, 77.0122136 ], "fees": 5000, "tags": [ "Good Faculty", "Great Sports" ], "rating": "4.5" } } ] } }
3.URI搜索
以下這些參數可使用統一資源標識符在搜索操做中傳遞 -
編號 | 參數 | 說明 |
---|---|---|
1 | Q | 此參數用於指定查詢字符串。 |
2 | lenient | 基於格式的錯誤能夠經過將此參數設置爲true 來忽略。默認狀況下爲false 。 |
3 | fields | 此參數用於在響應中選擇返回字段。 |
4 | sort | 能夠經過使用這個參數得到排序結果,這個參數的可能值是fieldName ,fieldName:asc 和fieldname:desc |
5 | timeout | 使用此參數限定搜索時間,響應只包含指定時間內的匹配。默認狀況下,無超時。 |
6 | terminate_after | 能夠將響應限制爲每一個分片的指定數量的文檔,當到達這個數量之後,查詢將提早終止。 默認狀況下不設置terminate_after 。 |
7 | 從命中的索引開始返回。默認值爲0 。 |
|
8 | size | 它表示要返回的命中數。默認值爲10 。 |
4.請求正文搜索
還能夠在請求正文中使用查詢DSL
來指定查詢,而且在前面的章節中已經給出了不少示例,
POST http://localhost:9200/schools/_search
請求正文
{
"query":{
"query_string":{
"query":"up"
}
}
}
JSON
響應
……………………………………………….
{
"_source":{
"name":"City School", "description":"ICSE", "street":"West End",
"city":"Meerut", "state":"UP", "zip":"250002", "location":[28.9926174, 77.692485],
"fees":3500, "tags":["Well equipped labs"],"rating":"4.5"
}
}
……………………………………………….
第三章:搜索
1.短語匹配
短語匹配用來解決準確匹配問題,例如匹配「頭痛」不會出現「頭暈」等近似詞。
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": "quick brown fox"
}
}
}
或者
"match": {
"title": {
"query": "quick brown fox",
"type": "phrase"
}
}
2.提升精度
使用"operator": "and"
提升精度或者 "minimum_should_match": "90%"
控制精度
symptom
:屬性,query
:查詢詞語
{
"query": {
"match": {
"symptom": {
"query": "Love You",
//"operator": "and",
"minimum_should_match": "90%"
}
}
}
}
3.組合查詢
使用組合查詢短語匹配含有symptom屬性爲「頭痛」,「噁心」這兩個詞語的文檔。match_phrase
短語匹配
{
"query": { "bool": { "must": { "match_phrase": { "symptom": "頭痛" }}, "must": { "match_phrase": { "symptom": "噁心" }} } } }
4.提升權重
boost
參數被用來提高一個語句的相對權重( boost
值大於 1
)或下降相對權重( boost
值處於 0
到 1
之間),可是這種提高或下降並非線性的,換句話說,若是一個 boost
值爲 2
,並不能得到兩倍的評分 _score
。
相反,新的評分 _score
會在應用權重提高以後被 歸一化 ,每種類型的查詢都有本身的歸一算法,細節超出了本書的範圍,因此不做介紹。簡單的說,更高的 boost
值爲咱們帶來更高的評分 _score
。
{
"query": { "bool": { "should": { "match": { "symptom": { "query": "頭痛", "type": "phrase", "boost": 3 } } }, "should": { "match": { "symptom": { "query": "噁心", "type": "phrase", "boost": 2 } } } } } }
5.分頁
size
顯示應該返回的結果數量,默認是 10
from
顯示應該跳過的初始結果數量,默認是 0
若是每頁展現 5 條結果,能夠用下面方式請求獲得 1 到 3 頁的結果:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
6.指定返回屬性
只返回查詢文檔的name和sysptom屬性。
{
"query": {
...
},
"_source": [
"name",
"symptom"
],
}
7.高亮搜索
{
"query": { "bool": { "must": { "match": { "symptom": { "query": "噁心", "minimum_should_match": "100%" } } } } },
"highlight": { "fields": { "symptom": {} } } }
第四章:SpringBoot
Spring Boot默認支持兩種技術來和ES交互,一種是Spring Data,一種是JEST(默認不生效)
1.SpringData
環境:IDEA+Spring Boot 1.5.13
首先明確elasticsearch的版本變化很是大,因此spring-boot-data-elasticsearch也針對不一樣版本寫了不一樣的集成,具體的版本適配能夠參考官方示例https://github.com/spring-projects/spring-data-elasticsearch,引用官方示例以下:
Add the Maven dependency:(增長Maven的依賴)
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>x.y.z.RELEASE</version>
</dependency>
If you’d rather like the latest snapshots of the upcoming major version, use our Maven snapshot repository and declare the appropriate dependency version.(若是您但願得到即將發佈的主要版本的最新快照,請使用咱們的Maven快照存儲庫並聲明適當的依賴版本。)
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>x.y.z.BUILD-SNAPSHOT</version>
</dependency>
<repository>
<id>spring-libs-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>http://repo.spring.io/libs-snapshot</url>
</repository>
spring data elasticsearch | elasticsearch |
---|---|
3.1.x | 6.2.2 |
3.0.x | 5.5.0 |
2.1.x | 2.4.0 |
2.0.x | 2.2.0 |
1.3.x | 1.5.2 |
好比個人Spring Boot項目爲1.5.13.RELEASE
,在IDEA左側能夠查看到elasticsearch的版本
那我能夠找到最接近的2.1.x
對應的elasticsearch版本爲2.4,咱們這個項目使用的是2.4.1徹底ok沒問題。
那咱們在application.yml配置一下服務器的elasticsearch地址:
spring:
data:
elasticsearch:
cluster-name: my-application
cluster-nodes: 服務器Ip:9300
cluster-name能夠在訪問9200端口時查看到。
而後咱們啓動項目測試一下,出現如圖所示,-測試沒問題。
2.依賴衝突
在實際項目中,咱們基本都須要其餘spring data 依賴,這時候啓動elasticsearch就會報錯,好比:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
再次啓動程序,報錯:
Caused by: java.lang.NoSuchFieldError: LUCENE_5_3_1
at org.elasticsearch.Version.<clinit>(Version.java:279) ~[elasticsearch-2.4.6.jar:2.4.6]
at org.elasticsearch.client.transport.TransportClient$Builder.build(TransportClient.java:131) ~[elasticsearch-2.4.6.jar:2.4.6]
咱們單獨啓動時正確,添加其它依賴後報錯,錯誤確定是依賴的緣由了。
咱們點擊挑戰到Version.java:279
查看他的源代碼:
public static final Version V_2_1_0 = new Version(V_2_1_0_ID, false, org.apache.lucene.util.Version.LUCENE_5_3_1);
也就是說elasticsearch-2.1.0適配LUCENE-5.3.1,而咱們的elasticsearch是2.4.6,繼續查看源代碼:
public static final Version V_2_4_6 = new Version(V_2_4_6_ID, false, org.apache.lucene.util.Version.LUCENE_5_5_4);
因此咱們須要LUCENE-5.5.4版本的依賴。
解決方法就是在pom.xml中導入依賴便可:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.5.4</version>
</dependency>
2.入門
A default implementation of ElasticsearchRepository, aligning to the generic Repository Interfaces, is provided. Spring can do the Repository implementation for you depending on method names in the interface definition.(提供了一個與通用存儲庫接口一致的ElasticsearchRepository的默認實現。Spring能夠根據接口定義中的方法名爲您實現存儲庫。 )
— 來自官方github
實現Elasticsearch的增刪改查就像咱們使用Spring data jpa同樣簡單快捷。
第一步,咱們先建立一個實體類用於測試。
@Document(indexName = "library",type = "book") //indexName索引名稱,type類別
public class Book {
private int id;
private String name;
private String anthony;
....
}
第二步,新建新建ElasticsearchRepository接口。
@Repository
public interface BookRepository extends ElasticsearchRepository<Book,Integer> {
Book findAllByName(String name);
}
第三步,測試。
@RunWith(SpringRunner.class)
@SpringBootTest
public class RobotsApplicationTests {
@Autowired
BookRepository bookRepository;
@Test
public void contextLoads() {
Book book = new Book("《西遊記後傳》","小白龍",1);
bookRepository.index(book); //保存
Book name = bookRepository.findAllByName("西遊記"); //查找
System.out.println(name);
}
}
查看打印:
Book{id=1, name='《西遊記後傳》', anthony='小白龍'}
第五章:JEST
JEST默認不生效,須要咱們導入依賴,JEST使用9200端口經過HTTP訪問ES。
1.導入依賴
<!-- JEST方式 -->
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
</dependency>
2.配置
spring:
elasticsearch:
jest:
uris: http://123.206.46.157:9200
username: elastic
password: changeme
read-timeout: 5000
connection-timeout: 5000
3.實體類
public class Book {
private int id;
private String name;
private String anthony;
.....
}
4.保存
@Autowired
private JestClient jestClient;
@Test
public void contextLoads() {
Book book = new Book("《西遊記後傳》","小白龍",120);
//構建一個索引功能 參數爲路徑.../library/old/1
Index index = new Index.Builder(book).index("library").type("old").id("3").build();
try {
//執行保存
jestClient.execute(index);
} catch (IOException e) {
e.printStackTrace();
}
}
5.查詢
此處的query語句參考前面講過的各類搜索方式。
String query = "{" +
" \"query\" : {" +
" \"match\" : {" +
" \"name\" : \"西遊\"" +
" }" +
" }" +
"}";
Search search = new Search.Builder(query).addIndex("library").addType("old").build();
try {
SearchResult result = jestClient.execute(search);
System.out.println(result.getJsonString());
} catch (IOException e) {
e.printStackTrace();
}
我的以爲:JEST查詢的不一樣與優點是能夠獲取所有的返回信息。
第六章:Repository
1.查詢
在ElasticsearchRepository中咱們可使用Not
Add
Like
Or
Between
等關鍵詞自動建立查詢語句。
如官方示例:
public interface BookRepository extends Repository<Book, String> {
List<Book> findByNameAndPrice(String name, Integer price);
List<Book> findByNameOrPrice(String name, Integer price);
Page<Book> findByName(String name,Pageable page);
Page<Book> findByNameNot(String name,Pageable page);
Page<Book> findByPriceBetween(int price,Pageable page);
Page<Book> findByNameLike(String name,Pageable page);
@Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}")
Page<Book> findByMessage(String message, Pageable pageable);
}
關鍵字
關鍵字 | 使用示例 | 等同於的ES查詢 |
---|---|---|
And | findByNameAndPrice | {「bool」 : {「must」 : [ {「field」 : {「name」 : 「?」}}, {「field」 : {「price」 : 「?」}} ]}} |
Or | findByNameOrPrice | {「bool」 : {「should」 : [ {「field」 : {「name」 : 「?」}}, {「field」 : {「price」 : 「?」}} ]}} |
Is | findByName | {「bool」 : {「must」 : {「field」 : {「name」 : 「?」}}}} |
Not | findByNameNot | {「bool」 : {「must_not」 : {「field」 : {「name」 : 「?」}}}} |
Between | findByPriceBetween | {「bool」 : {「must」 : {「range」 : {「price」 : {「from」 : ?,」to」 : ?,」include_lower」 : true,」include_upper」 : true}}}}} |
LessThanEqual | findByPriceLessThan | {「bool」 : {「must」 : {「range」 : {「price」 : {「from」 : null,」to」 : ?,」include_lower」 : true,」include_upper」 : true}}}}} |
GreaterThanEqual | findByPriceGreaterThan | {「bool」 : {「must」 : {「range」 : {「price」 : {「from」 : ?,」to」 : null,」include_lower」 : true,」include_upper」 : true}}}}} |
Before | findByPriceBefore | {「bool」 : {「must」 : {「range」 : {「price」 : {「from」 : null,」to」 : ?,」include_lower」 : true,」include_upper」 : true}}}}} |
After | findByPriceAfter | {「bool」 : {「must」 : {「range」 : {「price」 : {「from」 : ?,」to」 : null,」include_lower」 : true,」include_upper」 : true}}}}} |
Like | findByNameLike | {「bool」 : {「must」 : {「field」 : {「name」 : {「query」 : 「? *」,」analyze_wildcard」 : true}}}}} |
StartingWith | findByNameStartingWith | {「bool」 : {「must」 : {「field」 : {「name」 : {「query」 : 「? *」,」analyze_wildcard」 : true}}}}} |
EndingWith | findByNameEndingWith | {「bool」 : {「must」 : {「field」 : {「name」 : {「query」 : 「*?」,」analyze_wildcard」 : true}}}}} |
Contains/Containing | findByNameContaining | {「bool」 : {「must」 : {「field」 : {「name」 : {「query」 : 「?」,」analyze_wildcard」 : true}}}}} |
In | findByNameIn(Collectionnames) | {「bool」 : {「must」 : {「bool」 : {「should」 : [ {「field」 : {「name」 : 「?」}}, {「field」 : {「name」 : 「?」}} ]}}}} |
NotIn | findByNameNotIn(Collectionnames) | {「bool」 : {「must_not」 : {「bool」 : {「should」 : {「field」 : {「name」 : 「?」}}}}}} |
True | findByAvailableTrue | {「bool」 : {「must」 : {「field」 : {「available」 : true}}}} |
False | findByAvailableFalse | {「bool」 : {「must」 : {「field」 : {「available」 : false}}}} |
OrderBy | findByAvailableTrueOrderByNameDesc | {「sort」 : [{ 「name」 : {「order」 : 「desc」} }],」bool」 : {「must」 : {「field」 : {「available」 : true}}}} |
2.保存
@Autowired
private SampleElasticsearchRepository repository;
String documentId = "123456";
SampleEntity sampleEntity1 = new SampleEntity();
sampleEntity1.setId(documentId);
sampleEntity1.setMessage("some message");
String documentId2 = "123457"
SampleEntity sampleEntity2 = new SampleEntity();
sampleEntity2.setId(documentId2);
sampleEntity2.setMessage("test message");
List<SampleEntity> sampleEntities = Arrays.asList(sampleEntity1, sampleEntity2);
//bulk index
repository.save(sampleEntities);
3.更新
要作到這一點,只需使用相同的ID保存該對象性便可。
Book name = bookRepository.findAllById(100);
name.setAnthony("吳承恩"); //改變
bookRepository.save(name); //保存,此時ID不變
name = bookRepository.findAllById(100); //再次查找
System.out.println(name);
4.刪除
bookRepository.delete(1);
到此,Repository實現增刪改查完成!
第七章:模板
上面咱們使用了Spring data Jpa去實現增刪改查等操做,下面的方式是經過ElasticsearchTemplate模板結合Query實現保存與查找。
1.增長
IndexQuery的做用是保存對象到elasticsearch。用法以下。
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
Book book = new Book("《西遊記後傳》", "小白龍", 100);
IndexQuery indexQuery = new IndexQueryBuilder()
.withIndexName("library")
.withType("book")
.withId(book.getId()+"")
.withObject(book) //對象或集合
.build();
elasticsearchTemplate.index(indexQuery);
2.刪除
//第一種刪除具體的一條記錄
elasticsearchTemplate.delete("library","book",100+"");
//第二種刪除indexName/type/下的全部
DeleteQuery deleteQuery = new DeleteQuery();
deleteQuery.setIndex("library");
deleteQuery.setType("book");
elasticsearchTemplate.delete(deleteQuery);
//第三種刪除indexName/下的全部
elasticsearchTemplate.deleteIndex("library");
//第四種刪除查詢出來的全部
deleteQuery = new DeleteQuery();
deleteQuery.setQuery(QueryBuilders.matchQuery("id","100"));
elasticsearchTemplate.delete(deleteQuery);
3.更新
Book book = new Book("《西遊記後傳》", "豬八戒", 100);
UpdateQuery updateQuery = new UpdateQueryBuilder()
.withIndexName("library")
.withType("book")
.withId(book.getId()+"")
.build();
elasticsearchTemplate.update(updateQuery);
4.查詢
查詢不一樣於前面幾個,查詢比較複雜,好比模糊查詢,組合查詢,準確查詢等。這些變化來源於不一樣的QueryBuilder
,查詢的模板是相同的。以下:
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
Sort sort = new Sort(Sort.Direction.DESC, "id");//以id值爲準 降序排列,ASC爲升序
Pageable pageable = new PageRequest(0, 10, sort);//查看第0頁,以每頁10條劃分
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery()) // 自定義查詢(這是不一樣的地方)
.withPageable(pageable) // 自定義分頁
.build();
Page<Book> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery,Book.class);
System.out.println("頁數" + sampleEntities.getTotalPages());
System.out.println("行數" + sampleEntities.getTotalElements());
System.out.println("大小" + sampleEntities.getSize());
System.out.println("當前第幾頁" + sampleEntities.getNumber());
System.out.println("當前頁的數量"+sampleEntities.getNumberOfElements());
System.out.println("List<Book>:"+sampleEntities.getContent());
其它條件查詢下面講解!
第八章:術語
爲何要在插一節術語?是由於官方註釋比較晦澀,爲了方便下面的閱讀,能夠先了解下,若是已瞭解請跳過。
Analysis(分析)
分析的過程就是將全文(full text)轉換成 術語/分詞(terms)。 這取決於使用那個分析器,這些短語:「FOO BAR」, 「Foo-Bar」, 「foo,bar」,可能會拆分紅」 foo」和「bar」。這些拆分後的詞其實是存儲在索引中。一個完整的文本查詢(而不是一個分詞查詢) 「FoO:bAR」,將被分解成 「foo」,「bar」,來匹配存儲在索引中的分詞。正是這一過程的分析(包括在索引時間和搜索時間),容許elasticsearch執行全文查詢。
Cluster (集羣)
一個集羣包含一個或多個分配了相同的集羣名稱的節點。每一個集羣都有一個主節點是集羣自動選擇產生,而且能夠決定若是當前主節點失敗,哪些能夠替換。
Document(文檔)
文檔是存儲在elasticsearch中的一個JSON文件。這是至關與關係數據庫中表的一行數據。每一個文檔被存儲在索引中,並具備一個類型和一個id。一個文檔是一個JSON對象(也被稱爲在其餘語言中的 hash / hashmap / associative array(關聯數組)),其中包含零個或多個字段 或者 鍵值對。原始JSON文檔將被存儲在索引的_source字段,在得到(getting)或者 搜索(searching)默認的返回時,獲得或搜索文檔。
Id(標識)
每一個文檔ID標識了一個文檔。一個文檔的索引/類型/ ID必須是惟一的。若是沒有提供ID,將是自動生成。(還能夠看到路由)
Field(字段)
文檔中包含的一組字段或鍵值對。字段的值能夠是一個簡單的(標量)值(如字符串,整數,日期),或者一個嵌套的結構就像一個數組或對象。一個字段就是相似關係數據庫表中的一列。映射的每一個字段有一個字段的類型「type」(不要與文檔類型混淆),表示那種類型的數據能夠存儲在該字段裏,如:整數,字符串,對象。映射還容許你定義(除其餘事項外)一個字段的值如何進行分析。
Index(索引)
索引就是像關係數據庫中的「數據庫」。經過映射能夠定義成多種類型。索引是一個邏輯命名空間映射到一個或多個主要的分片,能夠有零個或多個副本分片。
Mapping(映射)
映射是像關係數據庫中的」模式定義「。每一個索引都有一個映射,它定義了每一個索引的類型,再加上一些索引範圍的設置。映射能夠被明確地定義,或者在一個文檔被索引的時候自動生成。
Node(節點)
節點是屬於elasticsearch羣集的運行實例。測試的時候,在一臺服務器能夠啓動多個節點,但一般狀況下應該在一臺服務器運行一個節點。在啓動時,節點將使用單播(或組播,可是必須指定)來發現使用相同的羣集名稱的羣集,並會嘗試加入該羣集。
Primary shard(主分片)
每一個文檔都存儲在一個主要分片上。當你索引一個文檔時,索引首先生成在主分片上,而後纔到主分片的全部副本上。默認狀況下,索引有5個主分片。您能夠指定更多或更少的主分片來適應索引能夠處理的文檔數。一旦建立了索引,就不能改變索引中主分片的數量。
Replica shard(副本分片)
每一個主分片能夠有零個或多個副本。副本是主分片的一個拷貝,有兩個做用:
一、故障轉移:若是主分片有問題,副本分片能夠提高爲主分片;
二、提升性能:獲取和搜索請求能夠處理主分片或副本分片。
默認狀況下,每一個主分片有一個副本,不過索引的副本數量能夠動態地改變。在同一個節點上,一個副本分片將永遠不會和其主分片一塊兒運行。
Routing(路由)
當你索引一個文檔,它是存儲在一個主分片裏。這分片的選擇是經過哈希的路由值。默認狀況下,路由值來自文檔的ID;若是該文檔指定了父文檔,則使用父文檔的ID(以確保這個子文檔和父文件都存儲在相同的分片上)。這個路由值能夠在索引的時候,經過指定數值或者配置字段映射來覆蓋。
Shard(分片)
一個分片是一個單一的Lucene的實例。這是一個低級別的經過ElasticSearch自動管理的「工做者」單元。索引是一個邏輯命名空間指向主分片和副本分片。索引的主分片和副本分片的數量須要明確的指定。然而你的代碼應該只處理一個索引。Elasticsearch分配集羣中全部節點的分片。在節點出現故障或增長新節點的時候,能夠自動的將一個節點上的分片移動到另外一個節點上。
Source field(源字段)
默認狀況下,你的JSON文檔將被索引存儲在_source字段裏面,全部的get(獲取)和search(搜索)請求將返回的該字段。這將容許你直接從搜索結果中訪問到源數據,而不須要再次發起請求檢索。
注:索引將返回完整的的JSON字符串給你,即便它包含無效的JSON。此字段裏的內容不表示任何該對象裏面的數據如何被索引。
Term(術語)
在elasticsearch裏,術語(term)是一個被索引的精確值。術語 foo, Foo,FOO 是不想等的。術語(即精確值)可使用「term」查詢接口來查詢。
Text(文本)
文本(或全文)是普通非結構化的文本,如本段。默認狀況下,文本將被分析成術語,術語纔是實際存儲在索引中。文本字段在索引時須要進行分析,以便全文搜索,全文查詢的關鍵字在搜索時,必須分析產生(搜索)與索引時相同的術語。
Type(類型)
Type是至關於關係數據庫中的「表」。每種類型都有一列字段,用來定義文檔的類型。映射定義了對在文檔中的每一個字段如何進行分析。
第九章:構建查詢
上面只是模糊的講了查詢模板,如今來仔細說說查詢!
首先你要明白QueryBuilder系列(MatchAllQueryBuilder.class,FuzzyQueryBuilder.class等)是什麼?
它們是具體的查詢實現類,它們是QueryBuilders抽象類的子類並實現了BoostableQueryBuilder<>接口。
而QueryBuilders的主要做用就是提供了靜態方法去建立一個子類的對象,方便QueryBuilder的構建與管理。
咱們從源碼的角度去分析它的一些方法!
匹配全部文檔的查詢。
matchAllQuery()
爲提供的字段名和文本建立類型爲「BOOLEAN」的匹配查詢。(解釋過來就是單個匹配,能夠模糊匹配)
matchQuery(String name, Object text) //name 字段值 ,text 查詢文本(不支持通配符)
爲提供的字段名和文本建立一個通用查詢。
commonTermsQuery(String name, Object text)
爲提供的字段名和文本建立類型爲「BOOLEAN」的匹配查詢。
multiMatchQuery(Object text, String... fieldNames)
爲提供的字段名和文本建立一個文本查詢,並輸入「短句」。
matchPhraseQuery(String name, Object text)
爲提供的字段名和文本建立一個與類型「PHRASE_PREFIX」匹配的查詢。
matchPhrasePrefixQuery(String name, Object text)
匹配包含術語的文檔的查詢。
termQuery(String name, Object value)
使用模糊查詢匹配文檔的查詢
fuzzyQuery(String name, Object value)
與包含指定前綴的術語的文檔相匹配的查詢。
prefixQuery(String name, String prefix)
在必定範圍內匹配文檔的查詢。
rangeQuery(String name)
實現通配符搜索查詢。支持的通配符是*,它匹配任何字符序列(包括空字符),而?它匹配任何單個字符。注意,這個查詢可能很慢,由於它須要遍歷許多項。爲了防止異常緩慢的通配符查詢,通配符項不該該以一個通配符*或?開頭。
wildcardQuery(String name, String query) //query 通配符查詢字符串
將包含術語的文檔與指定的正則表達式匹配的查詢
regexpQuery(String name, String regexp) //regexp的正則表達式
解析查詢字符串並運行它的查詢。有兩種模式。第一,當沒有字段添加(使用QueryStringQueryBuilder.field(字符串),將運行查詢一次,非前綴字段將使用QueryStringQueryBuilder.defaultField(字符串)。第二,當一個或多個字段添加(使用QueryStringQueryBuilder.field(String)),將運行提供的解析查詢字段,並結合使用DisMax或普通的布爾查詢(參見QueryStringQueryBuilder.useDisMax(布爾))。
queryStringQuery(String queryString)
相似於query_string查詢的查詢,但不會爲任何奇怪的字符串語法拋出異常。
simpleQueryStringQuery(String queryString)
可使用BoostingQuery類來有效地降級與給定查詢匹配的結果。
boostingQuery()
匹配與其餘查詢的布爾組合匹配的文檔的查詢
boolQuery()
建立一個可用於實現MultiTermQueryBuilder的子查詢的SpanQueryBuilder。
spanMultiTermQueryBuilder(MultiTermQueryBuilder multiTermQueryBuilder)
容許定義自定義得分函數的查詢。
functionScoreQuery(QueryBuilder queryBuilder, ScoreFunctionBuilder function)
更像這樣的查詢,查找「like」提供的文檔,例如提供的MoreLikeThisQueryBuilder.likeText(String),它是針對查詢所構造的字段進行檢查的
moreLikeThisQuery(String... fields)
構造一個新的非計分子查詢,包含子類型和要在子文檔上運行的查詢。這個查詢的結果是這些子文檔匹配的父文檔。
hasChildQuery(String type, QueryBuilder query)
構造一個新的非評分父查詢,父類型和在父文檔上運行的查詢。這個查詢的結果是父文檔匹配的子文檔。
hasParentQuery(String type, QueryBuilder query)
基於對其中任何一個項進行匹配的若干項的字段文件
termsQuery(String name, String... values)
一個查詢構建器,它容許構建給定JSON字符串或二進制數據做爲輸入的查詢。當您但願使用Java Builder API,但仍然須要將JSON查詢字符串與其餘查詢構建器結合時,這是很是有用的。
wrapperQuery(String source)
這些都是官方提供的註釋,有些晦澀難懂,還有不少,我這裏不一一列舉。
只須要明確一點,咱們使用上述靜態方法只是爲了方便建立QueryBuilder系列對象。
第十章:條件查詢
咱們調用QueryBuilders 的靜態方法建立完具體的QueryBuilder對象以後,傳入.withQuery(QueryBuilder)
方法就能夠實現的自定義查詢。
1.徹底匹配
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("字段名", "查詢文本");
2.短語匹配
好比你要查詢短語Love You
,當你使用QueryBuilders.matchQuery("name", "Love You")
時,可能會查詢到Love And You
這樣分開的結果,這時候咱們指定爲短語進行查詢:
QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery("name", "Love You");
3.模糊匹配
MoreLikeThisQueryBuilder queryBuilder = QueryBuilders
.moreLikeThisQuery("name")// 要匹配的字段, 不填默認_all
.like("西遊")// 匹配的文本
.minTermFreq(1);// 文本最少出現的次數(默認是2,咱們設爲1)
咱們再從源碼去看其它方法
添加一些文本以查找「相似」的文檔
addLikeText(String... likeTexts)
查找相似文檔
like(Item... likeItems)
設置不從其中選擇(好比咱們調用.like("西遊").unlike("西遊記")這樣會致使啥也查不到)
unlike(String... unlikeTexts)
添加一些文本以查找與此不一樣的文檔
addUnlikeText(String... unlikeTexts)
設置將包含在任何生成查詢中的查詢條件的最大數量。默認25
maxQueryTerms(int maxQueryTerms)
設置單詞被忽略的頻率,默認5,小於將不會被發現
minDocFreq(int minDocFreq)
設置單詞仍然出現的最大頻率。單詞出現更多的文檔將被忽略。默認爲無限
maxDocFreq(int maxDocFreq)
設置將被忽略的單詞的最小單詞長度,默認0
minWordLength(int minWordLength)
設置將被忽略的單詞的最大單詞長度,默認無限
maxWordLength(int maxWordLength)
設置中止詞,匹配時會忽略中止詞
stopWords(String... stopWords)
設置詞語權重,默認是1
boostTerms(float boostTerms)
查詢權重(默認1)
boost(float boost)
設置不從其中選擇術語的文本(文檔Item)
ignoreLike(String... likeText)
4.組合查詢
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name", "西遊")) //AND
.must(QueryBuilders.wildcardQuery("name", "西遊?")) //Not
.should(QueryBuilders.matchQuery("name", "西遊記")); //Or
5.包裹查詢
高於設定分數, 不計算相關性
QueryBuilder queryBuilder = QueryBuilders
.constantScoreQuery(QueryBuilders.matchQuery("name", "西遊記"))
.boost(2.0f);
6.範圍查詢
查詢id值在20-50之間的
QueryBuilder queryBuilder = QueryBuilders.rangeQuery("id")
.from("20")
.to("50")
.includeLower(true) // 包含上界
.includeUpper(true); // 包含下屆
7.通配符查詢
通配符查詢, 支持 * 匹配任何字符序列, 包括空
避免* 開始, 會檢索大量內容形成效率緩慢
單個字符用?
QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("user", "ki*hy");
8.過濾查詢
QueryBuilders.constantScoreQuery(FilterBuilders.termQuery("name", "kimchy")).boost(2.0f);
其實還有不少,未完待續。