Elasticsearch - 查询学习笔记

刚接触Elasticsearch,对于习惯了Sql的我有点无所适从,看似天马行空的查询(搜索)语句让初入ES的小白我有点难以接受,但是对照着《elasticsearch权威指南》试着敲了几天python_elasticsearch API后,发现与SQL还是有大量相似之处,因此写下这一份笔记为方便后续再阅读。

前期准备:

1. 安装配置好ES,网上很多资料,这里不再复述;

2. 往ES中插入一些数据,这里可以调用python的ES API中index方法插入,这里我预先插入了类似于如下的数据

{
  _index: "logstash-2018.01.09",
  _type: "logs",
  _id: "AWDaKEw14SpIsCUBj_Zd",
  _score: 1,
  _source: {
    remote_addr: "11.11.11.11",
    request: "GET /api/tag_info/?_id=1 HTTP/1.1",
    body_bytes_sent: 102,
    url: "/api/tag_info/",
    http_user_agent: "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0",
    remote_user: "-",
    path: "/data/logs/nginx/net.log",
    @timestamp: "2018-01-09T09:02:41.000Z",
    http_referer: "http://192.168.1.2/tag_info/",
    domain: "192.168.1.2",
    @version: "1",
    http_x_forwarded_for: "-",
    host: "192.168.1.2",
    responsetime: 0.002,
    status: "200"
  }
},


依据数据开始查询:

python要调用elasticsearch的查询,需要调用search(index, type, body, params)函数


1. 索引(index)、类型(type)的定义:

a. 查询时需要指定索引(index)与类型(type),我们可以理解为SQL需要指定库(databases)与表(table),查询条件写在body中,类似SQL中的where、order等

b. 索引(index)与类型(type)可以定义模糊字段,于SQL对照为select * from ind*.t*,类似search('ind*', 't*', {})

c. 甚至我们能定义多个索引多个类型,类似search('index1, index2', 'type1, type2', {}),search('_all', 'type1, type2', {})


以下是body的定义:


2. 单查询

a. 空查询,即查询所有数据(elasticsearch默认只查询10条,我们可以定义size),如下

body = {
    'size': 100,
    'query': {
        'match_all': {}
    }
}
以上语句类似于SQL的select * from index.type limit 100


b. 模糊匹配查询,若指定字段中的数据匹配了查询字符,则输出数据,并包含一个_score的匹配分数(分数越高,表示匹配度越高,默认排序越前)

body = {
    'size': 100,
    'query': {
        'match': {
            'body_bytes_sent': 102,
        }
    }
}
以上语句类似于SQL的 select * from index.type where body_bytes_send like '%102%' limit 100


c. 模糊多匹配查询,在多个字段中执行相同的match,若匹配上,则输出结果


body = {
    'size': 100,
    'query': {
        'multi_match': {
            'query': '10',
            'fields': ['host', 'body_bytes_send']
        }
    }
}
以上语句类似于SQL的 select * from index.type where host like '%10%' or body_bytes_send like '%10%' limit 100


d. 精确匹配查询若指定字段中的数据等于查询字符,则输出数据

body = {
    'size': 100,
    'query': {
        'term': {
            '@timestamp': '2018-01-09T09:02:41.000Z'
        }
    }
}
以上语句类似于SQL的 select * from index.type where @timestamp='2018-01-09T09:02:41.000Z' limit 100


e. 多值精确匹配,

body = {
    'size': 100,
    'query': {
        'terms': {
            '@timestamp': ['2018-01-09T09:02:41.000Z', '2018-01-09T10:35:21.000Z']
        }
    }
}
以上语句类似于SQL的 select * from index.type where  @timestamp in (' 2018-01-09T09:02:41.000Z ', '2018-01-09T10:35:21.000Z') limit 100


f. 指定数字或时间范围的匹配,当字段的类型为数字或者日期时,可以使用range指定查询的区间。这里需要对几个词语进行解释

gte (greaterthan andequal):  >=

gt (greaterthan): >

lte (lessthan andequal): <=

lt (lessthan): <

body = {
    'size': 100,
    'query': {
        'range': {
            'body_bytes_sent': {
                'lte': 102,
                'gt': 0,
            }
        }
    }
}
以上语句类似于SQL的 select * from index.type where body_bytes_sent>0 and  body_bytes_sent<=102 limit 100


g. 字段有值(exists)、字段无值(missing),返回字段非空(为空)的结果

body = {
    'size': 100,
    'query': {
        'exists': {
            'field': '@timestamp'
        }
    }
}

body = {
    'size': 100,
    'query': {
        'missing': {
            'field': '@timestamp'
        }
    }
}
以上语句类似于SQL的

select * from index.type where @timestamp not is null limit 100

select * from index.type where @timestamp is null limit 100



3. 复合查询
上面所写的都是单条查询,其实在使用时我们需要依据多个条件进行查询,类似于SQL中需要有and与or,因此这时候就需要复合查询来处理了。复合查询有如下关键字:

must:必须满足内部所有条件

must_not:必须不满足内部所有条件

should:满足内部任一条件,可为查询结果加分

filter:对结果进行再匹配(内部需要包含了must、must_not或者should),但是不会为结果进行近似度打分

如下例子可以展示一个复合查询

body = {
    'size': 100,	# 查询100条结果
    'query': {
        'bool': {
            'must': [
                {
                    'range': {
                        'body_bytes_sent': {
                            'gt': 0,
                            'lt': 100,
                        },
                    },
                },
                {
                    'match': {
                        'http_user_agent': 'AppleWebKit'
                    },
                },
            ],
            'filter': {
                'bool': {
                    'must_not': [
                        {
                            'range': {
                                'body_bytes_sent': {
                                    'gte': 20,
                                },
                            }
                        }
                    ],
                }
            }
        },
    }
}
以上语句解析为:

a. body_bytes_sent必须在(0, 100)之间;

b. http_user_agent必须包含AppleWebKit,同时系统会为http_user_agent相似度进行评分

c. body_bytes_sent大于等于20必须不成立

最终结果需要同时满足a、b、c,同时a与b会影响最终查询结果的_score大小


若我们关心所有条件的匹配相似度,那上面的body修改成:

body = {
    'size': 100,
    'query': {
        'bool': {
            'must': [
                {
                    'range': {
                        'body_bytes_sent': {
                            'gt': 0,
                            'lt': 100,
                        },
                    },
                },
            ],
            'must_not': [
                {
                    'range': {
                        'body_bytes_sent': {
                            'gte': 20,
                        }
                    }
                }
            ],
            'should': [
                {
                    'range': {
                        'body_bytes_sent': {
                            'lt': 20,
                        }
                    }
                },
                {
                    'match': {
                        'http_user_agent': 'AppleWebKit'
                    },
                },
            ],
        },
    }
}

最终以上的语句我们可以理解为SQL:

select * from index.type where (body_bytes_sent>0 and body_bytes_sent<100) and (body_bytes_sent<20) and (body_bytes_sent<20 or http_user_agent like '%AppleWebKit%')


4. 结果排序


a. 在未指定排序时,查询结果是依据_score来进行的


b. 指定排序,如下例子

body = {
    'size': 100,
    'query': {
        'range': {
            'body_bytes_sent': {
                'lte': 102,
                'gt': 0,
            }
        }
    },
    'sort': {
    	'body_bytes_sent': {
    		'order': 'desc'(或者'asc')
    	}
    }
}
以上语句类似于SQL:

select * from index.type where body_bytes_sent>0 and body_bytes_sent<=102 order by body_bytes_sent desc
其中desc为由大到小排序,asc为有小到大排序


c. 多级排序,如以下例子

body = {
    'size': 100,
    'query': {
        'range': {
            'body_bytes_sent': {
                'lte': 102,
                'gt': 0,
            }
        }
    },
    'sort': [
    	{
    	    'body_bytes_sent': {
    	        'order': 'desc'
    	    }
    	},
    	{
    	    '@timestamp': {
    	        'order': 'asc'
    	    }
    	},
    	
    ]
}
这是在body_bytes_sent的基础上增加了@timestamp排序,在 body_bytes_sent相同的基础上会依据@timestamp从小到大继续排序


这一下我们了解了普通搜索,组合搜索与排序,聚合后续再写了。





你可能感兴趣的:(elasticsearch,学习笔记)