深入搜索
es搜索分两个概念,匹配和过滤
匹配通常针对text类型,过滤则针对 integer,keyword,date
之所以加了通常二字,说明他们之间没有明确的规定,匹配可以去匹配data,integer等类型,过滤也可以去过滤text字段,
通过匹配的方式去找精确类型通常不会出现什么问题,通过过滤去找text类型的数据通常会得到意外的结果。
谨记:如果没有特殊情况,匹配针对text类型,过滤针对其他类型,
但是对于精确类型使用过滤的性能通常比匹配更高,所以能使用过滤的地方都过滤。
注意:这里要区别一下MySQL中的过滤概念,MySQL中的过滤是对查找后的数据进行过滤,而在ES中,过滤和匹配都等同于MySQL中的查找,
匹配适合查找模糊数据,过滤适合查找精确数据而已。
为了简化代码,下面的搜索都基于一下这份代码,更改的部分只是 $query:
常用过滤:
term(精确查找)
查找年龄为44的数据
$query = [
'query' => [
'term' => [
'age' => 44
]
]
];
terms(精确查找多个字段)
查找年龄为 44或55或66的数据
$query = [
'query' => [
'terms' => [
'age' => [44,55,66]
]
]
];
range(范围查找):
$query = [
'query' => [
'range' => [
'age' => [
'gt' => 43,
'lt' => 45
]
]
]
];
exists(等同于MySQL中的 is not null):
查找存在age属性的文档
$query = [
'query' => [
'exists' => [
'field' => 'age'
]
]
];
missing(等同于 MySQL中的 is null),
注意:这个过滤方法在2.x版本就废弃了,请使用 must_not 嵌套 exists 来实现
bool(用来组合其他过滤条件,包含 must,must_not,should操作)
$query = [
'query' => [
'bool' => [
'should' => [
'range' => [
'height' => ['gt' => 1.8]
]
],
'must_not' => [
'term' => [
'info.sex' => '女'
]
],
'must' => [
[
'term' => [
'info.country' => '法国'
]
],
[
'term' => [
'info.skin' => '白'
]
]
]
]
]
];
上面这个查询的意思是,身高应该大于1.8,性别不能是女,国家是法国且肤色是黑色。
这里country实际上是text类型,但是我任然通过过滤的方法找到了正确的值,但是这种方式是非常危险的,
这里之所以找到了正确的值,是因为country类型很简单,碰巧
analyzer(这里用的ik,如果是standard就没那么好运了)没有对其进行拆分。
常用的查询:
match(匹配一个字段)
$query = [
'query' => [
'match' => [
'height' => '1.8'
]
]
];
multi_match(匹配多个字段)
匹配姓和名里面包含 'Riley Libby Preston' 的数据
$query = [
'query' => [
'multi_match' => [
'query' => 'Riley Libby Preston',
'fields' => ['first_name','last_name']
]
]
];
bool(用来组合其他匹配条件,包含 must,must_not,should操作)
$query = [
'query' => [
'bool' => [
'should' => [
'match' => [
'height' => '1.8'
]
],
'must_not' => [
'match' => [
'info.sex' => '男'
]
]
]
]
];
在实际使用中,匹配和过滤都是混合搭配使用的,比如:
$query = [
'query' => [
'bool' => [
'should' => [
'match' => [
'height' => '1.8'
]
],
'must_not' => [
'term' => [
'info.sex' => '女'
]
],
'must' => [
[
'match' => [
'info.country' => '法国'
]
],
[
'match' => [
'info.skin' => '白'
]
]
]
]
]
];文档更新时间: 2020-09-10 14:37 作者:young