Elasticsearch实战
上一讲,我们说了,用most_fields策略,去实现cross-fields搜索,有3大弊端,而且搜索结果也显示出了这3大弊端
第一个办法:用copy_to,将多个field组合成一个field,问题其实就出在有多个field,有多个field以后,就很尴尬,我们只要想办法将一个标识跨在多个field的情况,合并成一个field即可。比如说,一个人名,本来是first_name,last_name,现在合并成一个full_name,不就ok了吗。。。。。
准备数据
PUT /forum?include_type_name=true
{
"mappings": {
"post":{
"properties":{
"first_name":{
"type":"text",
"copy_to":"full_name"
},
"last_name":{
"type":"text",
"copy_to":"full_name"
},
"full_name":{
"type":"text"
}
}
}
}
}
POST /forum/post/_bulk
{ "index": { "_id": "1"} }
{ "first_name" : "Peter", "last_name" : "Smith" }
{ "index": { "_id": "2"} }
{ "first_name" : "Smith", "last_name" : "Williams" }
{ "index": { "_id": "3"} }
{ "first_name" : "Jack", "last_name" : "Ma" }
{ "index": { "_id": "4"} }
{ "first_name" : "Robbin", "last_name" : "Li" }
{ "index": { "_id": "5"} }
{ "first_name" : "Tonny", "last_name" : "Peter Smith" }
查询
GET /forum/post/_search
{
"query": {
"match": {
"full_name": "Peter Smith"
}
}
}
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.4691012,
"hits" : [
{
"_index" : "forum",
"_type" : "post",
"_id" : "1",
"_score" : 1.4691012,
"_source" : {
"first_name" : "Peter",
"last_name" : "Smith"
}
},
{
"_index" : "forum",
"_type" : "post",
"_id" : "5",
"_score" : 1.2312969,
"_source" : {
"first_name" : "Tonny",
"last_name" : "Peter Smith"
}
},
{
"_index" : "forum",
"_type" : "post",
"_id" : "2",
"_score" : 0.5598161,
"_source" : {
"first_name" : "Smith",
"last_name" : "Williams"
}
}
]
}
}注意⚠️:很无奈,很多时候,我们很难复现。比如官网也会给一些例子,说用什么什么文本,怎么怎么搜索,是怎么怎么样的效果。es版本在不断迭代,这个打分的算法也在不断的迭代。所以我们其实很难说,对类似这几讲讲解的best_fields,most_fields,cross_fields,完全复现出来应有的场景和效果。
总结
问题1:只是找到尽可能多的field匹配的doc,而不是某个field完全匹配的doc --> 解决,最匹配的document被最先返回
问题2:most_fields,没办法用minimum_should_match去掉长尾数据,就是匹配的特别少的结果 --> 解决,可以使用minimum_should_match去掉长尾数据
问题3:TF/IDF算法,比如Peter Smith和Smith Williams,搜索Peter Smith的时候,由于first_name中很少有Smith的,所以query在所有document中的频率很低,得到的分数很高,可能Smith Williams反而会排在Peter Smith前面 --> 解决,Smith和Peter在一个field了,所以在所有document中出现的次数是均匀的,不会有极端的偏差
欢迎访问我的个人博客:小马博客