Elasticsearch应用(七)
1.查询文档的方式
- REST风格查询: 在请求URL中,直接将参数带过去
- DSL查询: Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询
- SQL查询: 在ES7之后,支持SQL语句查询文档。开源版本的ES并不支持通过Java操作SQL进行查询,如果需要操作SQL查询,则需要氯金(购买白金版)
2.DSL查询分类
- 全文检索(full text):全文检索查询,利用分词器对用户输入的内容进行分词,然后去倒排索引库中匹配
- 精确查询:根据精确词条值查找数据,一般是查找keyword,数值,日期,boolean等类型字段,精确查询不走倒排索引,会将整个文本插入到倒排索引库中
- 地理查询:根据经纬度查询
- 复合查询:复合查询可以将上述各种查询条件组合起来,合并查询条件
3.全文检索
match
介绍
match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找
默认多个词是or关系,只要有一个词匹配就会查询出来
参数
- query:指定匹配的值
- operator:匹配条件类型
- and:条件分词后都要匹配
- or:条件分词后有一个匹配即可(默认)
- minmum_should_match:最低匹配度,即条件在倒排索引中最低的匹配度,匹配几个词才行
示例
GET /[索引名称]/_search
{
"query":{
"match":{
"字段名":{
"query":"值",
"operator":"and",
"fuzziness": 2
"minmum_should_match":2
}
}
}
}
match_phrase
介绍
match_phrase查询分析文本并根据分析的文本创建一个短语查询。match_phrase会将检索关键词分词。match_phrase的分词结果必须在被检索字段的分词中都包含,而且顺序必须相同,而且默认必须都是连续的
参数
- slop:可以跳过分词后的词语数量
示例
GET /[索引名称]/_search
{
"query":{
"match_phrase":{
"address":{
"query":"广州白云山",
"slop":2
}
}
}
}
multi_match
介绍
可以根据字段类型,决定是否使用分词查询,得分最高的在前面
就是一个值同时匹配多个字段
示例
GET /[索引名称]/_search
{
"query":{
"multi_match":{
"query":"值",
"fields":["字段1","字段2"]
}
}
}
注意
字段类型分词,将查询条件分词之后进行查询,如果该字段不分词就会将查询条件作为整体进行查询
query_string
介绍
允许我们在单个查询字符串中指定AND | OR | NOT条件,同时也和multi_match query一样,支持多字段搜索。和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛
示例
// 不指定字段就是匹配所有字段
// 指定字段查询
GET /[index]/_search
{
"query":{
"query_string":{
"default_field":"字段名",
"query":"白云山 OR 橘子洲"
}
}
}
// 多字段查询
GET /[index]/_search
{
"query":{
"query_string":{
"fields":["字段名1","字段名2"],
"query":"张三 OR (广州 AND 王五)"
}
}
}
注意
查询字段分词就将查询条件分词查询,查询字段不分词将查询条件不分词查询
or and 啥的不要用小写
simple_query_string
介绍
类似Query String,但是会忽略错误的语法,同时只支持部分查询语法,不支持AND OR NOT,会当作字符串处理
特点
- +代替AND
- |代替OR
- -代替NOT
示例
GET /[index]/_search
{
"query":{
"simple_query_string":{
"fields":["字段名1","字段名2"],
"query":"张三 | (广州 + 王五)",
"default_operator":"AND" // 可以忽略和+使用一个即可
}
}
}
5.精确查询
term
介绍
Term用来使用关键词查询(精确匹配),还可以用来查询没有被进行分词的数据类型。Term是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term
match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般模糊查找的时候,多用match,而精确查找时可以使用term
什么类型分词
在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean ip 这些类型不分词,只有text类型分词
示例
GET /[索引名称]/_search
{
"query":{
"term":{
"字段名":{
"value":"值"
}
}
}
}
GET /[索引名称]/_search
{
"query":{
// 避免算分,而且term可以利用缓存
"constant_score":{
"filter":{
"term":{
// text是有子类型的,这样精确匹配就可以了
"address.keyword":"广州白云山公园"
}
}
}
}
}
注意
可以通过 Constant Score 将查询转换成一个 Filtering,避免算分,并利用缓存,提高性能
ids
介绍
指定多个ip匹配文档
示例
GET /[索引名称]/_search
{
"query":{
"ids":{
"values":[1001,1002]
}
}
}
mget
介绍
批量查询根据id
示例
GET /[索引名称]/_mget
{
"docs":[
{"index":"索引名","_id":id值},
{"index":"索引名","_id":id值}
]
}
GET /[索引名称]/_mget
{
"ids":["1","2"]
}
terms
暂时省略
prefix
介绍
它会对分词后的term进行前缀搜索
它不会分析要搜索字符串,传入的前缀就是想要查找的前缀
默认状态下,前缀查询不做相关度分数计算,它只是将所有匹配的文档返回,然后赋予所有相关分数值为1。它的行为更像是一个过滤器而不是查询。两者实际的区别就是过滤器是可以被缓存的,而前缀查询不行
原理
需要遍历所有倒排索引,并比较每个term是否已所指定的前缀开头
所以有性能问题
示例
GET /[索引名称]/_search
{
"query":{
"prefix":{
"字段名":{
"value":"值"
}
}
}
}
wildcard
介绍
通配符查询:工作原理和prefix相同,只不过它不是只比较开头,它能支持更为复杂的匹配模式
示例
GET /[索引名称]/_search
{
"query":{
"wildcard":{
"字段名":{
"value":"*白*"
}
}
}
}
range
介绍
范围查询
范围关键字
- range:范围关键字
- gte:大于等于
- lte:小于等于
- gt:大于
- lt:小于
- now:当前时间
示例
# 大于等于10小于等于20,gte大于等于,gt大于,lt小于,lte小于等于
GET /[索引名称]/_search
{
"query":{
"range":{
"字段名":{
"gte":10,
"lte":20
}
}
}
}
GET /[索引名称]/_search
{
"query":{
"range":{
"date":{
// 2年之前的数据
"gte":"now-2y"
}
}
}
}
fuzzy
介绍
在实际的搜索中,我们有时候会打错字,从而导致搜索不到。在Elasticsearch中,我们可以使用fuzziness属性来进行模糊查询,从而达到搜索有错别字的情形
参数
- fuzziness:表示输入的关键字通过几次操作可以转变成为ES库里面的对应field的字段,默认是0不开启
- prefix_length:表示限制输入关键字和ES对应查询field的内容开头的第n个字符必须完全匹配,不允许错别字匹配,默认值为0
示例
GET /es_db/_search
{
"query": {
"fuzzy": {
"address": {
"value": "白运山",
"fuzziness": 1
}
}
}
}
GET /es_db/_search
{
"query": {
"match": {
"address": {
"query": "广洲",
"fuzziness": 1
}
}
}
}
注意
- fuzzy 模糊查询 最大模糊错误 必须在0-2之间
- 搜索关键字长度为2,不允许存在模糊
- 搜索关键字长度为3-5,允许1次模糊
- 搜索关键字长度大于5,允许最多2次模糊
4.bool查询
介绍
一个bool查询,是一个或者多个查询子句的组合,总共包括4种子句,其中2种会影响算分,2种不影响算分
四种自句
- must: 相当于&& ,必须匹配,贡献算分
- should: 相当于|| ,选择性匹配,贡献算分
- must_not: 相当于! ,必须不能匹配,不贡献算分
- filter: 必须匹配,不贡献算分
两种Context
- 在Elasticsearch中,有Query和 Filter两种不同的Context
- Query Context: 相关性算分
- Filter Context: 不需要算分 ,可以利用Cache,获得更好的性能
算分注意事项
如果多条查询子句被合并为一条复合查询语句,比如 bool查询,则每个查询子句计算得出的评分会被合并到总的相关性评分中
其他注意事项
- 子查询可以任意顺序出现
- 可以嵌套多个查询
- 如果你的bool查询中,没有must条件,should中必须至少满足一条查询
语法
GET /[索引名称]/_search
{
"query":{
"bool":{
"must":[
{"term":{"city":"上海"}}
],
"should":[
{"term":{"brand":"皇冠假日"}},
{"term":{"brand":"华美达"}}
],
"must_not":[
{"range":{"price":{"lte":500}}}
],
"filter":[
{"range":{"score":{"gte":45}}}
]
}
}
}
5.function_score
介绍
控制相关度算分
示例
GET /[索引名]/_search
{
"query":{
"function_score":{
"query":{"match":{"all":"外滩"}},
"functions":[
{
"filter":{"term":{"id":"1"}},
"weight":10
}
],
"boost_mode":"multiply"
}
}
}
6.地理查询
介绍
ES提供地理查询支持
示例
# geo_bounding_box:查找geo_point值落在某个矩形范围的所有文档,字段名称就是文档类型为geo_point类型的字段
GET /[索引名]/_search
{
"query":{
"geo_bounding_box":{
"字段名称":{
"top_left":{
"laft":31.1,
"lon":121.5
},
"bottom_right":{
"lat":30.9,
"lon":121.7
}
}
}
}
}
# geo_distance:查询到指定中心小于某个距离值的所有文档
GET /[索引名]/_search
{
"query":{
"geo_distance":{
"distance":"15km",
"字段名称":"31.21,121.5"
}
}
}