基本增删改查

获取一个document

  1. curl -X GET http://localhost:9200/index/type/id

获取同一type的所有元素

  1. curl -X GET http://localhost:9200/index/type/_search

新增一个document

可以使用POST或PUT请求。

  1. curl -X POST http://localhost:9200/index/type/id -d '
  2. {
  3. "field": "value",
  4. ...
  5. }
  6. '

修改一个document

可以使用POST或PUT请求。

  1. curl -X PUT http://localhost:9200/index/type/id -d '
  2. {
  3. "field": "value",
  4. ...
  5. }
  6. '

删除一个document

  1. curl -X DELETE http://localhost:9200/index/type/id

检索操作

基本语法如下:

  1. curl -X POST http://localhost:9200/index/type/_search -d '
  2. {
  3. "query": {
  4. ...
  5. }
  6. }
  7. '

match_all

匹配所有的文档

  1. {
  2. "query": {
  3. "match_all": {}
  4. }
  5. }

match_none

和match_all相反,不匹配任何文档

  1. {
  2. "query": {
  3. "match_none": {}
  4. }
  5. }

match

  1. {
  2. "query": {
  3. "match": {
  4. "message": "hello world"
  5. }
  6. }
  7. }

match中检索的文本会被分词。默认来说分词后各个词组间的关系为or。该例子为查找出message字段包含hello或world的文档。

  1. {
  2. "query": {
  3. "match" : {
  4. "message" : {
  5. "query" : "this is a test",
  6. "operator" : "and"
  7. }
  8. }
  9. }
  10. }

通过增加operator参数,可以把默认的or关系修改为and。

match_phrase

  1. {
  2. "query": {
  3. "match_phrase": {
  4. "name": "软件公司"
  5. }
  6. }
  7. }

匹配的文档要求“软件公司”这四个字必须都出现,且按照顺序出现。

  1. {
  2. "query": {
  3. "match_phrase": {
  4. "name": {
  5. "query": "软件公司",
  6. "slop": 1
  7. }
  8. }
  9. }
  10. }

slop用来指定各个分词匹配时的最大间隔,即“软件X公司”也会被匹配。

多字段匹配

  1. {
  2. "query": {
  3. "multi_match" : {
  4. "query": "this is a test",
  5. "fields": [ "subject", "message" ]
  6. }
  7. }
  8. }

分别用”subject”和”message”字段内容匹配”this is a test”,如果任意一个字段匹配,该文档会出现在检索结果中。
匹配的fields也可以使用星号作为通配符。

  1. {
  2. "query": {
  3. "multi_match" : {
  4. "query": "Will Smith",
  5. "fields": [ "title", "*_name" ]
  6. }
  7. }
  8. }

查询title和以名称以_name结尾的字段。

  1. {
  2. "query": {
  3. "multi_match" : {
  4. "query" : "this is a test",
  5. "fields" : [ "subject^3", "message" ]
  6. }
  7. }
  8. }

提升subject的score权重(3倍于message)。

term

term查询关键字不进行分词处理。
官方文档原文描述如下:

The term query finds documents that contain the exact term specified in the inverted index.

  1. {
  2. "query": {
  3. "term": {
  4. "message": "some text"
  5. }
  6. }
  7. }

term的查询结果还与文档是否分词有关。如果文档内容不分词,大致相当于SQL中的”=”。
match和term的区别为:如果文档的有关字段进行了分词,match是搜索关键字的分词和文档字段的分词逐个比较,而term则是搜索关键字不分词,整个和文档字段的分词进行比较。

terms

  1. {
  2. "query": {
  3. "terms" : { "message" : ["some", "text"]}
  4. }
  5. }

查找message字段包含some或text的文档。

Query String 查询

  1. {
  2. "query": {
  3. "query_string" : {
  4. "default_field" : "content",
  5. "query" : "(new york city) OR (big apple)"
  6. }
  7. }
  8. }

new york citybig apple分别交给分词器处理。

Range Query

范围查询

  1. {
  2. "query": {
  3. "range" : {
  4. "age" : {
  5. "gte" : 10,
  6. "lte" : 20,
  7. "boost" : 2.0
  8. }
  9. }
  10. }
  11. }

可以使用的参数有:

  • gt: greater than
  • gte: greater than or equals
  • lt: less than
  • lte: less than or equals

    Exists

    字段存在查询

    1. {
    2. "query": {
    3. "exists" : { "field" : "user" }
    4. }
    5. }

    文档中user字段的值不能为null,user字段必须要存在。

    Prefix

    前缀查询

    1. {
    2. "query": {
    3. "prefix" : { "user" : "pe" }
    4. }
    5. }

    查找user字段以pe开头的文档(搜索关键字不分词)

    wildcard

    通配符查询

    1. {
    2. "query": {
    3. "wildcard" : { "user" : "pa*l" }
    4. }
    5. }

    可以匹配paul或paal等。为了保证性能,最好不要在开头使用通配符(比如匹配*aul)。
    通配符说明:

  • 星号(*)匹配0个或多个字符

  • 问号(?)匹配任意单个字符

    中英文单字(字母)匹配场景

    中文模糊搜索

  1. {
  2. "query": {
  3. "match_phrase": {
  4. "name": "公司"
  5. }
  6. }
  7. }

match_phrase 的意思为短语匹配,不仅要匹配短语的字,而且这些字出现的顺序也必须要匹配

英文按字母模糊搜索

  1. {
  2. "query": {
  3. "wildcard": {
  4. "name": "*aster*"
  5. }
  6. }
  7. }

布尔组合条件搜索

通过bool组合查询我们可以实现多个查询条件间andor逻辑组合关系。例如:

  1. {
  2. "query": {
  3. "bool": {
  4. "should": [
  5. {
  6. "wildcard": {
  7. "name": "*aster*"
  8. }
  9. }, {
  10. "match_phrase": {
  11. "authorList.name": "张"
  12. }
  13. }
  14. ]
  15. }
  16. }
  17. }

bool组合查询内有多种子句:

  • must 子句中的所有匹配必须都满足。
  • must_not 和must相反,子句中的所有匹配必须都不满足。
  • should 相当于或的关系,子句中的匹配只要至少有一个满足。如果存在must或filter子句,should中的条件默认不要求至少满足一个,即仅匹配must或filter子句且should中一个条件都不满足的文档也会被检索出来。如需设置至少满足的should条件个数,可以添加minimum_should_match参数。
  • filter 和must类似,不同的是搜索结果的匹配度评分会被忽略。

minimum_should_match示例:

  1. {
  2. "query": {
  3. "bool": {
  4. "should": [
  5. {
  6. "wildcard": {
  7. "fieldList.fieldName": "*?0*"
  8. }
  9. },
  10. {
  11. "match_phrase": {
  12. "fieldName.fieldComments": "?0"
  13. }
  14. }
  15. ],
  16. "filter": [
  17. {
  18. "term": {
  19. "systemId": "?1"
  20. }
  21. }
  22. ],
  23. "minimum_should_match": 1
  24. }
  25. }
  26. }

以上查询不仅要求filter语句满足,而且should中的条件至少要满足一个。
Bool查询更详细的用法请参考:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

嵌套对象字段的查询

  1. {
  2. "query": {
  3. "match_phrase": {
  4. "author.name": "Paul Jackson"
  5. }
  6. }
  7. }

检索出author对象中的name字段值为Paul Jackson的文档。

SpringBoot 整合Elasticsearch

SpringBoot 官方以为我们做好了elasticsearch的整合。对于常见的操作,我们不必再去编写json请求报文。
SpringBoot和elasticsearch官方starter名为:springboot starter data elasticsearch。下面是这个starter的使用方法。

加入依赖

pom.xml加入依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>

注意: Elasticsearch服务端版本号最好和springboot中依赖的elasticsearch.jar版本一致。 elasticsearch.jar的版本号可以通过查看项目依赖关系图得知。

建立Data Class

以Book这个类为例(使用了Project lombok)
Book.java:

  1. @Document(indexName = "database", type = "book")
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. @Data
  5. public class Book {
  6. private Long id;
  7. private String name;
  8. private List<Author> authorList; //支持嵌套元素
  9. }

Author.class

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Author {
  5. private String name;
  6. }

使用@Document注解来表示该bean是ES的文档,indexName为索引名称,type为索引类型。

注:可以使用@Field注解来修改字段默认的属性,比如是否索引,是否储存,使用什么分词器等。

建立Repository

  1. public interface BookRepo extends ElasticsearchCrudRepository<Book, Long> {
  2. // 解析方法名方式
  3. List<Book> findAllByNameContains(String name);
  4. // 自定义Query JSON方式
  5. @Query("{\"bool\":{\"must\":[{\"match_phrase\":{\"authorList.name\":\"?0\"}}]}}")
  6. List<Book> matchPhrase(String phrase);
  7. }

Repository需要继承ElasticsearchCrudRepository<T, ID>接口。
Repository自定义方法命名规则和Spring Data JPA用法完全一致。同样可以加入Pageable参数实现分页查询。
可以使用@Query注解来自定义查询。


除此之外也可以通过NativeSearchQueryBuilder的方式来查询elasticsearch。
代码如下:

  1. @Autowired
  2. private ElasticsearchTemplate elasticsearchTemplate;
  3. @Test
  4. public void nativeQueryBuilderTest() {
  5. NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
  6. .withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("authorList.name", "张三")))
  7. .build();
  8. List<Book> bookList = elasticsearchTemplate.queryForList(searchQuery, Book.class);
  9. System.out.println(bookList);
  10. }

我们使用QueryBuilders类来构造各种查询参数。
返回分页数据的例子:

  1. @Autowired
  2. private ElasticsearchTemplate elasticsearchTemplate;
  3. @Test
  4. public void nativeQueryBuilderTest() {
  5. NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().
  6. withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("authorList.name", "张三")))
  7. .withPageable(PageRequest.of(0, 20)) //加上分页参数
  8. .build();
  9. Page<Book> books = elasticsearchTemplate.queryForPage(searchQuery, Book.class); //获取Page类型结果
  10. System.out.println(books.getContent());
  11. }

参考文档

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/

作者:AlienPaul
链接:https://www.jianshu.com/p/72d21507a0b3
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。