Elasticsearch实战(八)--- 词条为中心的 CrossFields 多字段搜索策略

Elasticsearch实战- 词条为中心的Cross Fields 搜索策略

1.字段中心实现方式及问题
1.1 准备数据

empId:员工id, salary 表示薪资, deptName:部门, address:地址, provice:省份, city:市,area:区域
这里面有个数据是 专门构造的数据 “provice” : “湖北省”,“city”:“高新开发区”,“area”:“武汉” 为了演示 And 和 CrossFields区别用的

POST /testcross/_bulk
{"index":{"_id": 1}}
{"empId" : "111","name" : "员工1","age" : 20,"sex" : "男","mobile" : "19000001111","salary":1333,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"光谷大道","address":"湖北省武汉市洪山区光谷大厦","content" : "i like to write best elasticsearch article"}
{"index":{"_id": 2}}
{"empId" : "222","name" : "员工2","age" : 25,"sex" : "男","mobile" : "19000002222","salary":15963,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i think java is the best programming language"}
{"index":{"_id": 3}}
{ "empId" : "333","name" : "员工3","age" : 30,"sex" : "男","mobile" : "19000003333","salary":20000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"经济技术开发区","address" : "湖北省武汉市经济开发区","content" : "i am only an elasticsearch beginner"}
{"index":{"_id": 4}}
{"empId" : "444","name" : "员工4","age" : 20,"sex" : "女","mobile" : "19000004444","salary":5600,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"沌口开发区","address" : "湖北省武汉市沌口开发区","content" : "elasticsearch and hadoop are all very good solution, i am a beginner"}
{"index":{"_id": 5}}
{ "empId" : "555","name" : "员工5","age" : 20,"sex" : "男","mobile" : "19000005555","salary":9665,"deptName" : "测试部","provice" : "湖北省","city":"高新开发区","area":"武汉","address" : "湖北省武汉市东湖隧道","content" : "spark is best big data solution based on scala ,an programming language similar to java"}
{"index":{"_id": 6}}
{"empId" : "666","name" : "员工6","age" : 30,"sex" : "女","mobile" : "19000006666","salary":30000,"deptName" : "技术部","provice" : "武汉市","city":"湖北省","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i like java developer"}
{"index":{"_id": 7}}
{"empId" : "777","name" : "员工7","age" : 60,"sex" : "女","mobile" : "19000007777","salary":52130,"deptName" : "测试部","provice" : "湖北省","city":"黄冈市","area":"边城区","address" : "湖北省黄冈市边城区","content" : "i like elasticsearch developer"}
{"index":{"_id": 8}}
{"empId" : "888","name" : "员工8","age" : 19,"sex" : "女","mobile" : "19000008888","salary":60000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"汉阳区","address" : "湖北省武汉市江汉大学","content" : "i like spark language"}
{"index":{"_id": 9}}
{"empId" : "999","name" : "员工9","age" : 40,"sex" : "男","mobile" : "19000009999","salary":23000,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市郑州大学","content" : "i like java developer"}
{"index":{"_id": 10}}
{"empId" : "101010","name" : "张湖北","age" : 35,"sex" : "男","mobile" : "19000001010","salary":18000,"deptName" : "测试部","provice" : "湖北省","city":"武汉","area":"高新开发区","address" : "湖北省武汉市东湖高新","content" : "i like java developer i also like  elasticsearch"}
{"index":{"_id": 11}}
{"empId" : "111111","name" : "王河南","age" : 61,"sex" : "男","mobile" : "19000001011","salary":10000,"deptName" : "销售部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am not like  java "}
{"index":{"_id": 12}}
{"empId" : "121212","name" : "张大学","age" : 26,"sex" : "女","mobile" : "19000001012","salary":1321,"deptName" : "测试部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am java developer  thing java is good"}
{"index":{"_id": 13}}
{"empId" : "131313","name" : "李江汉","age" : 36,"sex" : "男","mobile" : "19000001013","salary":1125,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市二七区","content" : "i like java and java is very best i like it do you like java "}
{"index":{"_id": 14}}
{"empId" : "141414","name" : "王技术","age" : 45,"sex" : "女","mobile" : "19000001014","salary":6222,"deptName" : "测试部",,"provice" : "河南省","city":"郑州市","area":"金水区","address" : "河南省郑州市金水区","content" : "i like c++"}
{"index":{"_id": 15}}
{"empId" : "151515","name" : "张测试","age" : 18,"sex" : "男","mobile" : "19000001015","salary":20000,"deptName" : "技术部",,"provice" : "河南省","city":"郑州市","area":"高新开发区","address" : "河南省郑州高新开发区","content" : "i think spark is good"}

1.2 字段中心的MostFields 策略问题

词条为中西的搜索方式, 它将所有字段当成一个大字段,并在 每个字段 中查找 每个词
字段中心查询式,就是以字段为中心,代表就是 BestFields和MostFields把所有的字段全都散列,然后从中去查询
具体的查询方式我们已经在 上一篇文章 Elasticsearch实战(七)—BestFields MostFields CrossFields 多字段搜索策略中介绍过了,但是这种方式存在一些问题,场景如下:、

举个简单的例子,地址存储的时候 你不能直接存储 ”湖北省武汉市东湖高新区“ 这样的字符串,一个完整的地址需要用多个字段来唯一标识
一般存储的时候 省/市/区 分别是"provice", “city”, "area"三个字段,那我搜寻 湖北省 武汉市 江汉区 这个完整地址 的时候,会如何查询 provice=”湖北省“ , city=“武汉市” , area=“东湖高新” ?

如果用MostFields 是什么效果?

get /testcross/_search
{
  "query":{
    "multi_match": {
      "query": "湖北省 武汉市 江汉区",
      "fields": ["provice","city","area"],
      "type": "most_fields",
      "operator": "and" // 或者用 or 都是不行的
    }
  }
}
  1. 不支持 operator=AND,没有一个doc可以match到,因为你的关键字是分布在多个字段中的 用了 and 就是 provice包含 湖北省武汉市江汉区 或者 city包含 这三个词,后者 area包含这三个词, 没有一个doc能匹配,因为字段是打散的
  2. 如果用 operator = OR 出来几十条, 从语义上也是错误的, 会把所有 包含湖北省,武汉市 都搜出来,因为OR操作就是任一字段匹配,就会大量重复无用数据 比如出现 湖北省 XX市 XX区 的数据,甚至是 河南省 郑州市 江汉区的类似数据,
  3. 搜索不准确,因为MostFields 会把多个词 计算权重后参与最终分计算,累加求和,这就导致如果 有个 郑州市的江汉区,他的权重较高,然后会影响到 湖北省武汉市东湖高新 的排序,比他会优先排序

查询结果And和Or都不行
在这里插入图片描述

1.3 三个And操作 A&&B&&C 不满足

有人说 简单, 这不就是 三个And操作么?直接 bool must A && B && C

get /testcross/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match_phrase": {
            "provice": "湖北省"
          }
        },
        {
          "match_phrase": {
            "city": "武汉"
          }
        },
        {
          "match_phrase": {
            "area": "高新开发区"
          }
        }
      ]
    }
  }
}

看看结果 1条数据
似乎没什么问题, 但是 正常我们的搜索,很多时候我是不知道 他是具体什么字段的,比如我只知道 省/市/区 这三个ABC字段中包含了 湖北省,武汉,高新开发区的 查询字段, 就给我命中 返回,我不关心 哪个字段匹配上,只要三个字段都存在就行
到底是 A:湖北省 B:武汉 C:高新开发区
还是 A:武汉 B:湖北省,C:高新开发区
还是 A:湖北省, B:高新开发区,C:武汉
所以And也是不满足的
在这里插入图片描述

解决方案:

以上原因在于我们是在多个field中处理。我们也不关系具体哪些字段,我们只需要将多个field的信息整合成一个即可。就是本文讲的词条为中心的CrossFields 搜索

2.CrossFields 词条中心搜索方式
2.1 CrossFields 合并多字段变大字段查询处理

针对上面的查询 如果要用MostFields 查询的话,Operate And操作,解析完后

  1. provice 包含 湖北省 且 武汉市 且江汉区的 doc

  2. city 包含 湖北省 且 武汉市 且江汉区的 doc

  3. area 包含 湖北省 且 武汉市 且江汉区的 doc
    一定是搜不出来结果的
    如果是词条搜索的话,解析完后就是 ,词 湖北省 和 武汉市 和 江汉区 都必须出现,但是可以出现在任意字段中。

  4. provice 包含 湖北省 或者 武汉市 或者 江汉区

  5. 且 city 包含 湖北省 或者 武汉市 或者 江汉区

  6. 且 area 包含 湖北省 或者 武汉市 或者 江汉区

get /testcross/_search
{
  "query":{
    "multi_match": {
      "query": "湖北省 武汉 高新开发区",
      "fields": ["provice","city","area"],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

查询结果 :2条数据, 和三个And 操作查询结果不一致, 这才是我们想要的结果
我不关系具体哪个字段匹配上了, 我之关系, 只要这三个字段都能找到 就认为是命中结果,把三个字段当成大字段处理,只要三个搜索田间在大字段中全都存在 ,就认为满足
在这里插入图片描述

2.2 CrossFields 提高权重控制排名

可以查看刚才CrossFields的查询结果

员工分数
员工108.52814
员工57.311427

如果 provice, city 及area 每个词的权重不同, 比如 想要把city权重放的更高点,让权重优先的更考前的返回,我们可以直接在fields中计入 权重计算, 可以看到 city 被我改成了 city ^ 2 就是权重扩大 2倍,默认都是1倍

get /testcross/_search
{
  "query":{
    "multi_match": {
      "query": "湖北省 武汉 高新开发区",
      "fields": ["provice","city^2","area"],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

看下结果:
city:高新开发区的被提前了 ,因为 city:武汉 有很多个文档,但是city:高新开发区的就只有几个,所以 TFIDF模型认为 高新开发区 的权重在city字段上更有代表性,所以权重更大,这就影响了结果的排序
在这里插入图片描述


至此 我们已经能够 讲解了CrossFields 的用法及与BestFields和MostFields的区别 下一篇,我们讲一下 BestFields/MostFields/CrossFields 哪些参数可以影响他们的结果,参数到底有什么用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值