ES 入门 - 基于词项的查询
准备
首先先声明下,我这里使用的 ES 版本 5.2.0.
为了便于理解,这里以如下 index 为格式,该格式是通过 PMACCT 抓取的 netflow 流量信息, 文中所涉及的到的例子,全基于此 index.
本篇涉及的内容可以理解为 ES 的入门内容,主要针对词项的过滤,为基础篇。
{
"_index": "shflows_agg_1600358400",
"_type": "shflows_agg",
"_id": "node1_1600359600_0_172698718_shflows_agg_0",
"_score": 1.0,
"_source": {
"collector": "node1",
"src_port": "443",
"timestamp": 1600359600,
"device_ip": "1.1.1.1",
"flows": "40",
"dst_host": "2.2.2.2",
"TAG": 10001,
"router_ip": 172698718,
"dst_port": "16384",
"pkts": 40000,
"bits": 320000000000,
"src_host": "3.3.3.3"
}
},
在正式介绍搜索前,先明确一个概念。很多人在学习 ES 查询前,容易对 Term 和全文查询进行混淆。
首先,Term 是表达语义的最小单位,在搜索和利用统计语言模型时都需要处理 Term.
对应在 ES 里,针对 Term 查询的输入来说,不会做任何的分词处理,会把输入作为一个整体,在 ES 的倒排索引中进行词项的匹配,然后利用算分公式将结果返回。并可以通过 Constant Score 将查询转换为一个 Filtering,避免算分,利用缓存,从而提高性能。
虽然输入时,不做分词处理,但在搜索时,会做分词处理。这样有时就会出现无法搜索出结果的情况,比如有 name 为 ‘Jack’ 的 doc. 但如果在搜索时,输入 Jack,ES 是无法查询到的。必须改成小写的 jack 或者使用 keyword 进行查询。
Term 查询包含:
- Term Query
- Range Query
- Exists Query
- Prefix Query
- Wildcard Query
而全文查询,是基于全文本的查询。
在 ES 中,索引(输入)和搜索时都会分词。先将查询的字符串传递到合适分词器中,然后生成一个供查询的词项列表。
全文查询包括:
- Match Query
- Match Phrase Query
- Query String Query
而下面的例子全都是基于 Term 查询。
ES 搜索概述
ES 搜索 API 可以分为两大类:
- 基于 URL 的参数搜索, 适合简单的搜索。
- 基于 Request Body 的搜索(DSL),适合更为复杂的搜索。
确定查询的索引范围:
/_search
: 集群上的所有索引
/index1/_search
: index1 索引
``/index1,index2/_search`: index1 和 index2 索引
/index*/_search
: 以 index 开头的所有索引
URL 查询
指定字段查询:
使用 q 指定参数,通过KV 间键值对查询。
举例1:查询设备 IP 为 1.1.1.1
的相关文档信息:
/shflows_agg_*/_search?q=device_ip:1.1.1.1
{
"profile": "true"
}
profile 的意思是查看查询过程
结果:可以看到 type 为 TermQuery,搜索时根据指定字段:"device_ip:10.75.44.94"
"profile": {
"shards": [
{
"id": "[e_Ac3cNJRtmVxFW9DwOwjA][shflows_agg_1600531200][0]",
"searches": [
{
"query": [
{
"type": "TermQuery",
"description": "device_ip:1.1.1.1",
"time": "445.8407320ms",
............
泛查询
不明确指定查询的 key,只指定 value,会对文档中所有 key 进行匹配
举例2:查询各个属性中带有 1.1.1.1 字符的文档, 比如如果 src_host 或者 dst_host 中出现 1.1.1.1,相关文档也会被查询出来。
/shflows_agg_*/_search?q=10.75.44.94
{
"profile": "true"
}
结果:可以看到 description 变为 _all
"profile": {
"shards": [
{
"id": "[e_Ac3cNJRtmVxFW9DwOwjA][shflows_agg_1600531200][0]",
"searches": [
{
"query": [
{
"type": "TermQuery",
"description": "_all:1.1.1.1",
......
DSL 查询
方法:通过在 body 中,编写 json 进行更为复杂的查询
查询所有文档
举例1:查询当前 index 所有文档:
/shflows_agg_index1/_search
{
"query": {
"match_all": {} # 返回所有 doc
}
}
对文档进行排序和分页
举例2:查询当前 index 所有文档,按照时间排序
/shflows_agg_index1/_search
{
"from": 10,
"size": 20,
"sort": [{"timestamp": "desc"}],
"query": {
"match_all": {} # 返回所有 doc
}
}
指定文档返回的参数
举例:指定文档中,返回的仅是指定的参数
/shflows_agg_index1/_search
{
"_source": ["timestamp", "device_ip"],
"query": {
"match_all": {} # 返回所有 doc
}
}
使用脚本字段,对文档中的多个值进行脚本运算
举例:将文档中的,源 ip 和源端口进行拼接,并以 ip_address 进行命名:
/shflows_agg_index1/_search
{
"script_fields": {
"ip_address":{
"script": {
"lang": "painless",
"inline": "params.comment + doc['device_ip'].value + ':' + doc['dst_port'].value",
"params" : {
"comment" : "ip address is: "
}
}
}
},
"query": {
"match_all": {}
}
}
结果:在 fields 里多出了新的脚本拼接后的字段
{
"took": 84,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"failed": 0
},
"hits": {
"total": 36248845,
"max_score": 1.0,
"hits": [
{
"_index": "shflows_agg_1600358400",
"_type": "shflows_agg",
"_id": "node1_1600359600_0_172698718_shflows_agg_0",
"_score": 1.0,
"fields": {
"ip_address": [
"ip address is: 10.75.44.94:16384"
]
}
},
{
"_index": "shflows_agg_1600358400",
"_type": "shflows_agg",
"_id": "node1_1600359600_0_172698718_shflows_agg_5",
"_score": 1.0,
"fields": {
"ip_address": [
"ip address is: 10.75.44.94:443"
]
}
},
.......
Query Context OR Filter Context 查询
在 ES 中,搜索过程有 Query 和 Filter 上下文两种:
- Query 查询:在搜索过程中会进行相关性的算分操作
- Filter 查询:不需要进行算分,所以可以利用缓存,获得更好的性能
在 Query 和 Filter 查询里可以进行:
- 等值查询(term)
- 范围查询(range)
举例:如查询 dst_port 为 443 的 doc,并打分
/shflows_agg_index1/_search
{
"profile": "true",
"explain": true,
"query": {
"term": {"dst_port": 443}
}
}
结果:
{
"took": 191,
"timed_out": false,
"_shards": {
"total": 11,
"successful": 11,
"failed": 0
},
"hits": {
"total": 3871488,
"max_score": 2.2973032,
"hits": [
{
"_shard": "[shflows_agg_1600358400][0]",
"_node": "RWTixYPtTieZaRgAH0NOkQ",
"_index": "shflows_agg_1600358400",
"_type": "shflows_agg",
"_id": "node1_1600359600_0_172698718_shflows_agg_5",
"_score": 2.2973032, ####### 可以看到这里有计算的分数
"_source": {
"collector": "node1",
"src_port": "16384",
"timestamp": 1600359600,
使用 filter 查询:
/shflows_agg_index1/_search
{
"profile": "true",
"explain": true,
"query": {
# 使用 constant_score 不进行算分操作
"constant_score": {
"filter": {
"term": {
"dst_port": 443
}
}
}
}
}
结果:
"hits": {
"total": 3872768,
"max_score": 1.0, # 1.0 为固定值
.....
"profile": {
"shards": [
{
"id": "[e_Ac3cNJRtmVxFW9DwOwjA][shflows_agg_1600531200][0]",
"searches": [
{
"query": [
{
"type": "ConstantScoreQuery", ## 不变分数查询
"description": "ConstantScore(dst_port:443)",
举例:terms 查询,查询 dst_port 为 443 和 22 doc
/shflows_agg_index1/_search
{
"profile": "true",
"explain": true,
"query": {
# 使用 constant_score 不进行算分操作
"constant_score": {
"filter": {
"terms": {
"dst_port": [443,22]
}
}
}
}
}
举例:数据范围查询
{
"profile": "true",
"explain": true,
"query": {
"constant_score": {
"filter": {
"range": {
"timestamp": {
# 大于等于
"gte": 1601049600,
# 小于等于
"lte": 1601308800
}
}
}
}
}
}
Bool 复合查询:多个条件进行筛选
在 ES 可以通过 bool 查询,将一个或者多个查询子句组合或者嵌套到一起,实现更为复杂的查询。
bool 查询共包含 4 个子句:
- must:搜索的结果必须匹配,参与算分
- should:选择性匹配,类似于 OR,满足一个条件就可以,参与算分
- must_not: 必须不能匹配,属于 Filter context,不贡献算分
- filter:必须匹配,属于 Filter context ,不贡献算分。
must_not 和 filter 性能更好,不需要算分。
举例:查询时间范围在 1601171628 和 1601175228 之间,目的端口为 80,源目的 IP 在 [1.1.1.1 ,1.1.1.2, 1.1.1.3] 中任意一个的 doc 信息。
{
"profile": "true",
"explain": true,
"query": {
"bool": {
"must": [
{
"range": {
"timestamp": {
"gte": 1601171628,
"lte": 1601175228
}
}
},
{
"term": {
"dst_port": 80
}
},
{
"bool": {
# 注意这里 should 在 must 的数组里,如果和 must 同级,是无法影响 must 的结果的。
"should": [
{
"term": {
"src_host": "1.1.1.1"
}
},
{
"term": {
"src_host": "1.1.1.1"
}
},
{
"term": {
"src_host": "1.1.1.1"
}
}
]
}
}
]
}
}
}
参考
ES 入门 - 基于词项的查询的更多相关文章
- ElasticStack学习(九):深入ElasticSearch搜索之词项、全文本、结构化搜索及相关性算分
一.基于词项与全文的搜索 1.词项 Term(词项)是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term. Term的使用说明: 1)Term Level Query:Ter ...
- ES 入门记录之 match和term查询的区别
ElasticSearch 系列文章 1 ES 入门之一 安装ElasticSearcha 2 ES 记录之如何创建一个索引映射 3 ElasticSearch 学习记录之Text keyword 两 ...
- Elasticsearch入门教程(五):Elasticsearch查询(一)
原文:Elasticsearch入门教程(五):Elasticsearch查询(一) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- es创建普通索引以及各种查询
创建索引 创建普通索引: PUT /my_index { "settings": { "index": { "number_of_shards&quo ...
- Elasticsearch入门教程(六):Elasticsearch查询(二)
原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- ES入门及安装软件
es介绍 Elasticsearch,简称es,是一款高扩展的分布式全文检索引擎.它可以近乎实时的存储,检索数据.es是面向文档型的数据库,一条数据就是一个文档,用json做为文档序列化的格式.es是 ...
- ES 入门之一 安装ElasticSearcha
安装ElasticSearcha 学习ES也有快一个月了,但是学习的时候一直没有总结.以前没有总结是因为感觉不会的很多,现在对ES有一点了解了.索性就从头从安装到使用ES做一个详细的总结,也分享给其他 ...
- 转:arcgis api for js入门开发系列四地图查询
原文地址:arcgis api for js入门开发系列四地图查询 arcgis for js的地图查询方式,一般来说,总共有三种查询方式:FindTask.IdentifyTask.QueryTas ...
- MyBatis基础入门《二》Select查询
MyBatis基础入门<二>Select查询 使用MySQL数据库,创建表: SET NAMES utf8mb4; ; -- ---------------------------- -- ...
随机推荐
- Java面试题(Java Web篇)
Java Web 64.jsp 和 servlet 有什么区别? jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将 ...
- 【Go语言探险】线上奇怪日志问题的排查
最近在日志中发现一些奇怪的日志,大致长这样: Error 2020-08-28 06:59:38.813+00:00 ... _msg=get immersion context, fetch tra ...
- 把Autofac玩的和javaSpring一样6
大家好,今天来介绍我开源的一个autofac.Annotation项目 源码:https://github.com/yuzd/Autofac.Annotation 本项目是autofa的一个扩展组件, ...
- Spring Security如何优雅的增加OAuth2协议授权模式
一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...
- PHP弱类型hash比较缺陷
成因分析: == 在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较 0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0. 因此CTF比赛中需要用到弱类型H ...
- codewars贪吃蛇算法题目
有这样一个题目: Given an n x n array, return the array elements arranged from outermost elements to the mid ...
- Centos7.6系统下docker的安装
一.环境说明 系统:CentOS7.6 软件:Docker19.03 二.Docker的安装 2.1.在线安装 (1) 设置仓库,安装所需的软件包. yum-utils 提供了 yum-config- ...
- 13_Python的面向对象编程-类class,对象object,实例instance
1.面向对象概述 1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组 2.对象是由类实例化出来的一个具体的对象 属性: 对象拥有的名词,用变量表示 ...
- UEFI、BIOS、GPT、MBR等概念的辨析
(本文转移自本人的旧博客) 从各个地方包括知乎,Wiki,CSDN搜索到的一些整理,这些概念极易混淆. 先说互相的关系 BIOS和UEFI是两种固件接口标准 MBR和GPT是两种分区表 Legacy模 ...
- 解决Maven下载速度缓慢问题
解决Maven下载速度缓慢问题 第一步:找到自己安装maven的路径,选择setting.xml D:\apache-maven-3.2.2\conf\settings.xml 第二步:打开setti ...