Elasticsearch安裝和配置問題
啟動時候報錯的問題
max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
max number of threads [1024] for user [lishang] likely too low, increase to at least [2048]
max number of threads [1024] for user [lish] likely too low, increase to at least [2048]
解決方案:
切換root用戶修改/etc/security/limits.conf
添加如下內(nèi)容:
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
修改/etc/systemctl.conf
添加如下配置:
vm.max_map_count=655360
接下來執(zhí)行命令:
sysctl -p
即可解決啟動報錯問題。
無法以root用戶啟動
Elasticsearch默認不建議用戶使用root用戶運行。如果需要使用root賬戶可以使用以下啟動腳本:
./elasticsearch -Des.insecure.allow.root=true
Elasticsearch HTTP操作
基本增刪改查
獲取一個document
curl -X GET http://localhost:9200/index/type/id
獲取同一type的所有元素
curl -X GET http://localhost:9200/index/type/_search
新增一個document
可以使用POST或PUT請求。
curl -X POST http://localhost:9200/index/type/id -d '
{
"field": "value",
...
}
'
修改一個document
可以使用POST或PUT請求。
curl -X PUT http://localhost:9200/index/type/id -d '
{
"field": "value",
...
}
'
刪除一個document
curl -X DELETE http://localhost:9200/index/type/id
檢索操作
基本語法如下:
curl -X POST http://localhost:9200/index/type/_search -d '
{
"query": {
...
}
}
'
match_all
匹配所有的文檔
{
"query": {
"match_all": {}
}
}
match_none
和match_all相反,不匹配任何文檔
{
"query": {
"match_none": {}
}
}
match
{
"query": {
"match": {
"message": "hello world"
}
}
}
match中檢索的文本會被分詞。默認來說分詞后各個詞組間的關(guān)系為or。該例子為查找出message字段包含hello或world的文檔。
{
"query": {
"match" : {
"message" : {
"query" : "this is a test",
"operator" : "and"
}
}
}
}
通過增加operator參數(shù),可以把默認的or關(guān)系修改為and。
match_phrase
{
"query": {
"match_phrase": {
"name": "軟件公司"
}
}
}
匹配的文檔要求“軟件公司”這四個字必須都出現(xiàn),且按照順序出現(xiàn)。
{
"query": {
"match_phrase": {
"name": {
"query": "軟件公司",
"slop": 1
}
}
}
}
slop用來指定各個分詞匹配時的最大間隔,即“軟件X公司”也會被匹配。
多字段匹配
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
分別用"subject"和"message"字段內(nèi)容匹配"this is a test",如果任意一個字段匹配,該文檔會出現(xiàn)在檢索結(jié)果中。
匹配的fields也可以使用星號作為通配符。
{
"query": {
"multi_match" : {
"query": "Will Smith",
"fields": [ "title", "*_name" ]
}
}
}
查詢title和以名稱以_name結(jié)尾的字段。
{
"query": {
"multi_match" : {
"query" : "this is a test",
"fields" : [ "subject^3", "message" ]
}
}
}
提升subject的score權(quán)重(3倍于message)。
term
term查詢關(guān)鍵字不進行分詞處理。
官方文檔原文描述如下:
The term query finds documents that contain the exact term specified in the inverted index.
{
"query": {
"term": {
"message": "some text"
}
}
}
term的查詢結(jié)果還與文檔是否分詞有關(guān)。如果文檔內(nèi)容不分詞,大致相當于SQL中的"="。
match和term的區(qū)別為:如果文檔的有關(guān)字段進行了分詞,match是搜索關(guān)鍵字的分詞和文檔字段的分詞逐個比較,而term則是搜索關(guān)鍵字不分詞,整個和文檔字段的分詞進行比較。
terms
{
"query": {
"terms" : { "message" : ["some", "text"]}
}
}
查找message字段包含some或text的文檔。
Query String 查詢
{
"query": {
"query_string" : {
"default_field" : "content",
"query" : "(new york city) OR (big apple)"
}
}
}
將new york city和big apple分別交給分詞器處理。
Range Query
范圍查詢
{
"query": {
"range" : {
"age" : {
"gte" : 10,
"lte" : 20,
"boost" : 2.0
}
}
}
}
可以使用的參數(shù)有:
- gt: greater than
- gte: greater than or equals
- lt: less than
- lte: less than or equals
Exists
字段存在查詢
{
"query": {
"exists" : { "field" : "user" }
}
}
文檔中user字段的值不能為null,user字段必須要存在。
Prefix
前綴查詢
{
"query": {
"prefix" : { "user" : "pe" }
}
}
查找user字段以pe開頭的文檔(搜索關(guān)鍵字不分詞)
wildcard
通配符查詢
{
"query": {
"wildcard" : { "user" : "pa*l" }
}
}
可以匹配paul或paal等。為了保證性能,最好不要在開頭使用通配符(比如匹配*aul)。
通配符說明:
- 星號(*)匹配0個或多個字符
- 問號(?)匹配任意單個字符
中英文單字(字母)匹配場景
中文模糊搜索
{
"query": {
"match_phrase": {
"name": "公司"
}
}
}
match_phrase 的意思為短語匹配,不僅要匹配短語的字,而且這些字出現(xiàn)的順序也必須要匹配
英文按字母模糊搜索
{
"query": {
"wildcard": {
"name": "*aster*"
}
}
}
布爾組合條件搜索
通過bool組合查詢我們可以實現(xiàn)多個查詢條件間and或or邏輯組合關(guān)系。例如:
{
"query": {
"bool": {
"should": [
{
"wildcard": {
"name": "*aster*"
}
}, {
"match_phrase": {
"authorList.name": "張"
}
}
]
}
}
}
bool組合查詢內(nèi)有多種子句:
- must 子句中的所有匹配必須都滿足。
- must_not 和must相反,子句中的所有匹配必須都不滿足。
- should 相當于或的關(guān)系,子句中的匹配只要至少有一個滿足。如果存在must或filter子句,should中的條件默認不要求至少滿足一個,即僅匹配must或filter子句且should中一個條件都不滿足的文檔也會被檢索出來。如需設(shè)置至少滿足的should條件個數(shù),可以添加
minimum_should_match參數(shù)。 - filter 和must類似,不同的是搜索結(jié)果的匹配度評分會被忽略。
minimum_should_match示例:
{
"query": {
"bool": {
"should": [
{
"wildcard": {
"fieldList.fieldName": "*?0*"
}
},
{
"match_phrase": {
"fieldName.fieldComments": "?0"
}
}
],
"filter": [
{
"term": {
"systemId": "?1"
}
}
],
"minimum_should_match": 1
}
}
}
以上查詢不僅要求filter語句滿足,而且should中的條件至少要滿足一個。
Bool查詢更詳細的用法請參考:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
嵌套對象字段的查詢
{
"query": {
"match_phrase": {
"author.name": "Paul Jackson"
}
}
}
檢索出author對象中的name字段值為Paul Jackson的文檔。
SpringBoot 整合Elasticsearch
SpringBoot 官方以為我們做好了elasticsearch的整合。對于常見的操作,我們不必再去編寫json請求報文。
SpringBoot和elasticsearch官方starter名為:springboot starter data elasticsearch。下面是這個starter的使用方法。
加入依賴
pom.xml加入依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
注意:
Elasticsearch服務(wù)端版本號最好和springboot中依賴的elasticsearch.jar版本一致。
elasticsearch.jar的版本號可以通過查看項目依賴關(guān)系圖得知。
建立Data Class
以Book這個類為例(使用了Project lombok)
Book.java:
@Document(indexName = "database", type = "book")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Book {
private Long id;
private String name;
private List<Author> authorList; //支持嵌套元素
}
Author.class
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Author {
private String name;
}
使用@Document注解來表示該bean是ES的文檔,indexName為索引名稱,type為索引類型。
注:可以使用@Field注解來修改字段默認的屬性,比如是否索引,是否儲存,使用什么分詞器等。
建立Repository
public interface BookRepo extends ElasticsearchCrudRepository<Book, Long> {
// 解析方法名方式
List<Book> findAllByNameContains(String name);
// 自定義Query JSON方式
@Query("{\"bool\":{\"must\":[{\"match_phrase\":{\"authorList.name\":\"?0\"}}]}}")
List<Book> matchPhrase(String phrase);
}
Repository需要繼承ElasticsearchCrudRepository<T, ID>接口。
Repository自定義方法命名規(guī)則和Spring Data JPA用法完全一致。同樣可以加入Pageable參數(shù)實現(xiàn)分頁查詢。
可以使用@Query注解來自定義查詢。
除此之外也可以通過NativeSearchQueryBuilder的方式來查詢elasticsearch。
代碼如下:
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void nativeQueryBuilderTest() {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("authorList.name", "張三")))
.build();
List<Book> bookList = elasticsearchTemplate.queryForList(searchQuery, Book.class);
System.out.println(bookList);
}
我們使用QueryBuilders類來構(gòu)造各種查詢參數(shù)。
返回分頁數(shù)據(jù)的例子:
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void nativeQueryBuilderTest() {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().
withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("authorList.name", "張三")))
.withPageable(PageRequest.of(0, 20)) //加上分頁參數(shù)
.build();
Page<Book> books = elasticsearchTemplate.queryForPage(searchQuery, Book.class); //獲取Page類型結(jié)果
System.out.println(books.getContent());
}
參考文檔
Elasticsearch 官方文檔: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
SpringBoot starter data elasticsearch官方文檔: https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/