簡明Elasticsearch使用教程

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 citybig 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)多個查詢條件間andor邏輯組合關(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/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容