简明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

添加如下内容:

* soft nofile 65536

* hard nofile 131072

* soft nproc 2048

* hard nproc 4096

修改/etc/systemctl.conf

添加如下配置:

vm.max_map_count=655360

接下来执行命令:

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

{
    "query": {
        "match" : {
            "message" : {
                "query" : "this is a test",
                "operator" : "and"
            }
        }
    }
}

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

match_phrase

{
    "query": {
        "match_phrase": {
            "name": "软件公司"
        }
    }
}

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

{
    "query": {
        "match_phrase": {
            "name": {
                "query": "软件公司",
                "slop": 1
            }
        }
    }
}

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

多字段匹配

{
  "query": {
    "multi_match" : {
      "query": "this is a test",
      "fields": [ "subject", "message" ] 
    }
  }
}

分别用"subject"和"message"字段内容匹配"this is a test",如果任意一个字段匹配,该文档会出现在检索结果中。

匹配的fields也可以使用星号作为通配符。

{
  "query": {
    "multi_match" : {
      "query": "Will Smith",
      "fields": [ "title", "*_name" ] 
    }
  }
}

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

{
  "query": {
    "multi_match" : {
      "query" : "this is a test",
      "fields" : [ "subject^3", "message" ] 
    }
  }
}

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

term

term查询关键字不进行分词处理。

官方文档原文描述如下:

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

{
    "query": {
        "term": {
            "message": "some text"
        }
    }
}

term的查询结果还与文档是否分词有关。如果文档内容不分词,大致相当于SQL中的"="。

match和term的区别为:如果文档的有关字段进行了分词,match是搜索关键字的分词和文档字段的分词逐个比较,而term则是搜索关键字不分词,整个和文档字段的分词进行比较。

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
            }
        }
    }
}

可以使用的参数有:

  • 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开头的文档(搜索关键字不分词)

wildcard

通配符查询

{
    "query": {
        "wildcard" : { "user" : "pa*l" }
    }
}

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

  • 星号(*)匹配0个或多个字符
  • 问号(?)匹配任意单个字符

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

中文模糊搜索

{
    "query": {
        "match_phrase": {
            "name": "公司"
        }
    }
}

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

英文按字母模糊搜索

{
    "query": {
        "wildcard": {
            "name": "*aster*"
        }
    }
}

布尔组合条件搜索

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

{
    "query": {
        "bool": {
            "should": [
                {
                    "wildcard": {
                        "name": "*aster*"
                    }
                    
                }, {
                    "match_phrase": {
                        "authorList.name": "张"
                    }
                }
            ]
            
        }
    }
}

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

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

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服务端版本号最好和springboot中依赖的elasticsearch.jar版本一致。
elasticsearch.jar的版本号可以通过查看项目依赖关系图得知。

建立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自定义方法命名规则和Spring Data JPA用法完全一致。同样可以加入Pageable参数实现分页查询。
可以使用@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类来构造各种查询参数。

返回分页数据的例子:

@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)) //加上分页参数
            .build();
    Page<Book> books = elasticsearchTemplate.queryForPage(searchQuery, Book.class); //获取Page类型结果
    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/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容