ElasticSearch应用 - 使用

ES的几种调用方式

restful api调用(http请求)

GET请求:http://localhost:9200/

curl可以模拟发送请求:curl -X GET "localhost:9200/?pretty"

ES的启动端口

  1. 9200:给外部用户(客户端)调用的端口
  2. 9300:给ES集群内部通信的(外部无法使用)

kibana devtools

自由地对ES进行操作(本质也是restful api),不建议生产环境使用

客户端调用

支持 Java, JavaScript, Ruby, Go, .NET, PHP, Python等多种客户端的调用。

使用方法

基础的增删改查,已有

EQL查询

事件查询语言(EQL)是一种用于基于事件的时间序列数据(如日志、度量和跟踪)的查询语言。

EQL的优势

  • EQL可以让你表达事件之间的关系。
  • EQL的学习曲线很低。
  • EQL是为安全用例而设计的。
GET /my-data-stream/_eql/search
{
  "query": """
    process where process.name == "regsvr32.exe"
  """
}
1
2
3
4
5
6

返回

EQL查询结果:

{
    "is_partial": false,
    "is_running": false,
    "took": 60,
    "timed_out": false,
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "events": [
            {
                "_index": ".ds-my-data-stream-2099.12.07-000001",
                "_id": "OQmfCaduce8zoHT93o4H",
                "_source": {
                    "@timestamp": "2099-12-07T11:07:09.000Z",
                    "event": {
                        "category": "process",
                        "id": "aR3NWVOs",
                        "sequence": 4
                    },
                    "process": {
                        "pid": 2012,
                        "name": "regsvr32.exe",
                        "command_line": "regsvr32.exe  /s /u /i:https://...RegSvr32.sct scrobj.dll",
                        "executable": "C:\\Windows\\System32\\regsvr32.exe"
                    }
                }
            },
            {
                "_index": ".ds-my-data-stream-2099.12.07-000001",
                "_id": "xLkCaj4EujzdNSxfYLbO",
                "_source": {
                    "@timestamp": "2099-12-07T11:07:10.000Z",
                    "event": {
                        "category": "process",
                        "id": "GTSmSqgz0U",
                        "sequence": 6,
                        "type": "termination"
                    },
                    "process": {
                        "pid": 2012,
                        "name": "regsvr32.exe",
                        "executable": "C:\\Windows\\System32\\regsvr32.exe"
                    }
                }
            }
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

SQL查询

学习成本低,与原来的数据库查询语言一致。

POST /_sql?format=txt
{
  "query": "SELECT * FROM library WHERE release_date < '2000-01-01'"
}
1
2
3
4

结果

    author     |     name      |  page_count   | release_date
---------------+---------------+---------------+------------------------
Dan Simmons    |Hyperion       |482            |1989-05-26T00:00:00.000Z
Frank Herbert  |Dune           |604            |1965-06-01T00:00:00.000Z
1
2
3
4

Painless Scripting language

编程式取值,更灵活,但是学习成本高

Mapping

可以理解为数据库的表结构,有哪些字段、字段类型。(没有指定字段类型,自动生成;也可以手动指定字段类型)

ES支持动态mapping, 表结构可以动态改变,而不像MySQL一样必须手动建表,没有的字段就不能插入。

显示创建mapping:

GET user/_mapping

PUT /user
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  }, 
      "name":   { "type": "text"  }     
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

分词器

指定了分词的规则。

  • 分词器 (opens new window)

  • Standard Analyzer 标准分词器

    • 根据Unicode文本分割算法的定义,将文本划分为单词边界上的术语。它删除了大多数标点符号,降低了术语的小写,并支持删除停止词。
  • Simple Analyzer 简单分词器

    • 每当遇到不是字母的字符时,简单分析器就会将文本划分为多个术语。它将文本全部转换成小写。
  • Whitespace Analyzer 空格分词器

    • 每当遇到任何空白字符时,空白分析器都会将文本划分为多个术语。它没有小写的转换。
  • Stop Analyzer 停止分词器

    • 与简单分析器类似,但也支持删除停止词。
  • Keyword Analyzer 关键字分词器

    • 是一个“noop”分析器,它接受给定的任何文本,并输出与单个术语完全相同的文本。
  • Pattern Analyzer 模式分词器

    • 使用正则表达式将文本拆分为术语。它支持小写和停止字。
  • Language Analyzers 语言分词器

    • Elasticsearch提供了许多特定于语言的分析器,如英语或法语或中文(ik,pinyin)。
  • Fingerprint Analyzer 指纹分词器

    • 是一种专业的分析仪,可以创建可用于重复检测的指纹。

DSL

写DSL查询语句时,先测试原生DSL,再翻译成客户端语言

DSL搜索条件:

{
    "query": {
        "bool": {
            "must_not": {
                "match": {
                    "title": ""
                }
            },
            "should": [
                {
                    "match": {
                        "title": ""
                    }
                },
                {
                    "match": {
                        "desc": ""
                    }
                }
            ],
            "filter": [
                {
                    "term": {
                        "isDelete": 0
                    }
                },
                {
                    "term": {
                        "id": 1
                    }
                },
                {
                    "term": {
                        "tags": "java"
                    }
                },
                {
                    "term": {
                        "tags": "框架"
                    }
                }
            ],
            "minimum_should_match": 1
        }
    },
    "from": 0, //分页
    "size": 5, //分页
    "_source": [
        "name",
        "_createTime",
        "desc",
        "reviewStatus",
        "priority",
        "tags"
    ], //需要查询的字段
    "sort": [ //排序
        {
            "priority": {
                "order": "desc"
            }
        },
        {
            "_score": {
                "order": "desc"
            }
        },
        {
            "_createTime": {
                "order": "desc"
            }
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

java代码:

package src;

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 过滤
boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
if (id != null) {
    boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
}
if (notId != null) {
    boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));
}
if (userId != null) {
    boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));
}
// 必须包含所有标签
if (CollectionUtils.isNotEmpty(tagList)) {
    for (String tag : tagList) {
boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));
    }
}
// 包含任何一个标签即可
if (CollectionUtils.isNotEmpty(orTagList)) {
    BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();
    for (String tag : orTagList) {
orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));
    }
    orTagBoolQueryBuilder.minimumShouldMatch(1);
    boolQueryBuilder.filter(orTagBoolQueryBuilder);
}
// 按关键词检索
if (StringUtils.isNotBlank(searchText)) {
    boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));
    boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));
    boolQueryBuilder.minimumShouldMatch(1);
}
// 按标题检索
if (StringUtils.isNotBlank(title)) {
    boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));
    boolQueryBuilder.minimumShouldMatch(1);
}
// 按内容检索
if (StringUtils.isNotBlank(content)) {
    boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));
    boolQueryBuilder.minimumShouldMatch(1);
}
// 排序
SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
if (StringUtils.isNotBlank(sortField)) {
    sortBuilder = SortBuilders.fieldSort(sortField);
    sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
}
// 分页
PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
// 构造查询
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
.withPageable(pageRequest).withSorts(sortBuilder).build();
SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

动静分离设计:先模糊筛选静态数据,查出数据后,再根据查到的内容id去数据库查找到动态数据。类似MySQL的聚簇索引,二次查找的原理