深入搜索

es搜索分两个概念,匹配和过滤

匹配通常针对text类型,过滤则针对 integer,keyword,date
之所以加了通常二字,说明他们之间没有明确的规定,匹配可以去匹配data,integer等类型,过滤也可以去过滤text字段,
通过匹配的方式去找精确类型通常不会出现什么问题,通过过滤去找text类型的数据通常会得到意外的结果。
谨记:如果没有特殊情况,匹配针对text类型,过滤针对其他类型,
但是对于精确类型使用过滤的性能通常比匹配更高,所以能使用过滤的地方都过滤。
注意:这里要区别一下MySQL中的过滤概念,MySQL中的过滤是对查找后的数据进行过滤,而在ES中,过滤和匹配都等同于MySQL中的查找,
匹配适合查找模糊数据,过滤适合查找精确数据而已。
为了简化代码,下面的搜索都基于一下这份代码,更改的部分只是 $query:

常用过滤:
term(精确查找)
查找年龄为44的数据
$query = [
    'query' => [
        'term' => [
            'age' => 44
        ]
    ]
];

terms(精确查找多个字段)
查找年龄为 445566的数据
$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