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 city
和big 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组合查询我们可以实现多个查询条件间and
或or
逻辑组合关系。例如:
{
"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/