在前文中,介绍了Elasticsearch-php的一些基本API,链接:PHP Elasticsearch的连接与基本使用。本文将就搜索进行探讨:
一、匹配查询:
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'from' => 0, //从第几天开始返回
'size' => 2, //返回结果数量 limit
'query' => [
'constant_score' => [ //非评分模式执行
'filter' => [
'term' => [
'name' => 'saki'
]
]
]
]
]
];
$res = $this->es->search($params);
from-size:从第多少条开始查询n条记录,用于分页,在返回的数据集较大时建议使用scroll。
query:查询语句,与filter的区别在于其会根据_source计算文档的相似度,加之filter会自动缓存结果,故而filter性能更高。
constant_score:不使用检索词的频率对查询结果进行排序。
term 完全匹配(不支持一个term下添加多个条件), 如果需要分词后进行匹配使用 match,下面举例说明两者的区别:
例如有两条记录 “name”:“yukari” ,“name”:“yukari is always 17 years old” 此时的搜索条件是 yukari is,如果在name是'index'=> 'analyzed'的情况下,第二条记录name会被分词为 yukari ,is,always……,match查询会将yukari is分为yukari和is,而且yukari和is只要有一个词以上匹配到,就会返回结果,所以match会返回两条结果。而term则会使用yukari is(yukari is这个查询条件不会被分词)去和原句分词后的结果做匹配,即(yukari,is,always……),没有一个是与yukari is匹配的,所以返回空集。同理,即使用“yukari is always 17 years old”做term搜索,也是空集。故而需要用term做精确搜索时,一定要设置'index'=> 'not_analyzed',即原句不被分词。
二、布尔查询:
//must = and must_not= not should=or
$json = '{
"query" : {
"bool" : {
"should" : [
{ "term" : { "age" : 19 } },
{ "term" : { "age" : 17 } }
],
"must" : [
{ "term" : { "name" : "saki" } }
]
}
}
}';
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => $json,
];
其中must可以理解为and ,must_not理解为not,should理解为or,但需要注意以下几点:
1、在bool查询中,如果存在must或者filter与should在一起的情况,如果should中没有一个匹配,也会返回根据must或者filter匹配的结果。如果只有一个should,那么必须至少匹配should中的一条才会返回结果。所以,一定注意,上例中bool下的should与must不是and关系!
2、注意上例的写法与其他查询条件的写法有区别,body使用的是一个json字符串,而不像其他例子一样使用数组。由于布尔运算的包含关系以及php数组对象转json对象的问题,虽然Elasticsearch-php官方API中提供了下面的写法:
'should' => [
[ 'term' => [ 'age' => 18 ] ],
[ 'term' => [ 'age' => 19 ] ],
],
请注意‘term’两边多出的“[”符合。但是请一定直接使用json字符串,以避免返回结果与预期不一致!
三、多条件匹配查询,相当于in:
$params3 = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'query' => [
'constant_score' => [
'filter' => [
'terms' => [
'name' => ['yukari','saki']
]
]
]
]
]
];
四、范围查询,gt >, lt <, gte >=, lte <=:
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'query' => [
'constant_score' => [
'filter' => [
'range' => [
'age' => [
'gt' => 16,
'lt' => 18
]
]
]
]
]
]
];
五、基于距离的模糊查询:
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'query' => [
'fuzzy' => [
'name' => [
"value" =>"yuki", //模糊的字段
"fuzziness" => 2,
]
]
]
]
];
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'query' => [
'wildcard' => [
"name" =>"s*i*",
]
]
]
];
再次重复一下,在name是'index'=> 'analyzed'的情况下,模糊搜索也是基于分词结果的,例如,正如上面的例子,“yukari”和“yukari is always 17 years old”,y*i可以搜索到两条记录,但是y*o却搜索不到一条记录。
关于搜索,还有许多需要学习总结的地方,待后续继续介绍。