elasticsearch查询之keyword字段的查询打分控制

2023-11-02

一、数据情况

purchase记录每个用户的购买信息;

PUT purchase
{
    "mappings":{
        "properties":{
            "id":{
                "type":"keyword"
            },
            "name":{
                "type":"text"
            },
            "goods":{
                "properties":{
                    "id":{
                        "type":"keyword"
                    },
                    "name":{
                        "type":"text"
                    }
                }
            }
        }
    }
}

index 三个document

PUT purchase/_doc/1
{
  "id":1,
  "name":"sam",
  "goods":[
    {"id":"g1","name":"ipad"},
    {"id":"g2","name":"iphone"}
  ]
}


PUT purchase/_doc/2
{
  "id":2,
  "name":"coco",
  "goods":[
    {"id":"g1","name":"ipad"},
    {"id":"g2","name":"iphone"},
    {"id":"g3","name":"ipod"}
  ]
}


PUT purchase/_doc/3
{
  "id":3,
  "name":"jim",
  "goods":[
    {"id":"g1","name":"ipad"},
    {"id":"g2","name":"iphone"},
    {"id":"g3","name":"ipod"},
    {"id":"g4","name":"TV"}
  ]
}

查看索引数据情况

POST purchase/_search
{
  "query": {
    "match_all": {}
  }
}

{
    "took":331,
    "timed_out":false,
    "_shards":{
        "total":1,
        "successful":1,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":{
            "value":3,
            "relation":"eq"
        },
        "max_score":1,
        "hits":[
            {
                "_index":"purchase",
                "_id":"1",
                "_score":1,
                "_source":{
                    "id":1,
                    "name":"sam",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        }
                    ]
                }
            },
            {
                "_index":"purchase",
                "_id":"2",
                "_score":1,
                "_source":{
                    "id":2,
                    "name":"coco",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        },
                        {
                            "id":"g3",
                            "name":"ipod"
                        }
                    ]
                }
            },
            {
                "_index":"purchase",
                "_id":"3",
                "_score":1,
                "_source":{
                    "id":3,
                    "name":"jim",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        },
                        {
                            "id":"g3",
                            "name":"ipod"
                        },
                        {
                            "id":"g4",
                            "name":"TV"
                        }
                    ]
                }
            }
        ]
    }
}

二、查询需求

我们需要查询购买过某种商品的顾客,一般我们可以通过ui的业务逻辑得到需要筛选的一些商品的id,由于id字段是一个不需要分词的keyword字段,所以我们会直接使用term级别的查询;


POST purchase/_search
{
  "query": {
    "terms": {
      "goods.id": [
        "g2",
        "g3",
        "g4"
      ]
    }
  }
}

我们可以看到查询结果中的三条记录的权重打分都是1;正常情况下购买商品越多的客户,相对来说价值更大即命中的权重得分越大;

{
    "took":0,
    "timed_out":false,
    "_shards":{
        "total":1,
        "successful":1,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":{
            "value":3,
            "relation":"eq"
        },
        "max_score":1,
        "hits":[
            {
                "_index":"purchase",
                "_id":"1",
                "_score":1,
                "_source":{
                    "id":1,
                    "name":"sam",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        }
                    ]
                }
            },
            {
                "_index":"purchase",
                "_id":"2",
                "_score":1,
                "_source":{
                    "id":2,
                    "name":"coco",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        },
                        {
                            "id":"g3",
                            "name":"ipod"
                        }
                    ]
                }
            },
            {
                "_index":"purchase",
                "_id":"3",
                "_score":1,
                "_source":{
                    "id":3,
                    "name":"jim",
                    "goods":[
                        {
                            "id":"g1",
                            "name":"ipad"
                        },
                        {
                            "id":"g2",
                            "name":"iphone"
                        },
                        {
                            "id":"g3",
                            "name":"ipod"
                        },
                        {
                            "id":"g4",
                            "name":"TV"
                        }
                    ]
                }
            }
        ]
    }
}

三、terms查询分析

我们使用_explain分析一下terms查询怎么打分的;

POST purchase/_explain/3
{
  "query": {
    "terms": {
      "goods.id": [
        "g2",
        "g3",
        "g4"
      ]
    }
  }
}

我们可以看到elasticsearch最终使用ConstantScore查询重写的terms查询,此查询默认权重打分为1;

{
  "_index" : "purchase",
  "_id" : "3",
  "matched" : true,
  "explanation" : {
    "value" : 1.0,
    "description" : "ConstantScore(goods.id:g2 goods.id:g3 goods.id:g4)",
    "details" : [ ]
  }
}

terms提供的查询参数十分有限,其中涉及权重的只有boost,但是这只是针对整个terms查询,而不是内部的子查询;

POST purchase/_explain/3
{
  "query": {
    "terms": {
      "goods.id": [
        "g2",
        "g3",
        "g4"
      ],
      "boost":2
    }
  }
}

{
  "_index" : "purchase",
  "_id" : "3",
  "matched" : true,
  "explanation" : {
    "value" : 2.0,
    "description" : "ConstantScore(goods.id:g2 goods.id:g3 goods.id:g4)^2.0",
    "details" : [ ]
  }
}

四、构建子查询打分

match是elasticsearch提供的一个跟terms类似的查询,由于goods.id的type是keyword,所以需要给match指定一个查询时的analyzer,才能保证输入的几个id分开作为不同的查询;

POST purchase/_search
{
  "query": {
    "match": {
      "goods.id": {
        "query": "g2 g3 g4",
        "analyzer":"standard"
      }
    }
  }
}


{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 2.178501,
    "hits" : [
      {
        "_index" : "purchase",
        "_id" : "3",
        "_score" : 2.178501,
        "_source" : {
          "id" : 3,
          "name" : "jim",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            },
            {
              "id" : "g4",
              "name" : "TV"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "2",
        "_score" : 0.8298607,
        "_source" : {
          "id" : 2,
          "name" : "coco",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "1",
        "_score" : 0.18360566,
        "_source" : {
          "id" : 1,
          "name" : "sam",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            }
          ]
        }
      }
    ]
  }
}

通过查看文档3的打分情况,我们可以看到elasticsearch先针对每个关键字计算打分,然后将三项打分的和作为最终的打分;在这里我们也可以看到elasticsearch内部会自动将match查询rewrite为三个子查询;

POST purchase/_explain/3
{
  "query": {
    "match": {
      "goods.id": {
        "query": "g2 g3 g4",
        "analyzer":"standard"
      }
    }
  }
}

{
  "_index" : "purchase",
  "_id" : "3",
  "matched" : true,
  "explanation" : {
    "value" : 2.178501,
    "description" : "sum of:",
    "details" : [
      {
        "value" : 0.18360566,
        "description" : "weight(goods.id:g2 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      },
      {
        "value" : 0.646255,
        "description" : "weight(goods.id:g3 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      },
      {
        "value" : 1.3486402,
        "description" : "weight(goods.id:g4 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      }
    ]
  }
}

我们也可以通过bool查询,使用它的should在查询之前手动组建多个子查询;

POST purchase/_search
{
  "query": {
    "bool": {
      "should": [
        {"term": {"goods.id": "g2"}},
        {"term": {"goods.id": "g3"}},
        {"term": {"goods.id": "g4"}}
      ],
      "minimum_should_match": 1
    }
  }
}

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 2.178501,
    "hits" : [
      {
        "_index" : "purchase",
        "_id" : "3",
        "_score" : 2.178501,
        "_source" : {
          "id" : 3,
          "name" : "jim",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            },
            {
              "id" : "g4",
              "name" : "TV"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "2",
        "_score" : 0.8298607,
        "_source" : {
          "id" : 2,
          "name" : "coco",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "1",
        "_score" : 0.18360566,
        "_source" : {
          "id" : 1,
          "name" : "sam",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            }
          ]
        }
      }
    ]
  }
}

在bool查询中,通过查看文档3的打分情况,我们可以看到elasticsearch也是先针对每个关键字计算打分,然后将三项打分的和作为最终的打分;

POST purchase/_explain/3
{
  "query": {
    "bool": {
      "should": [
        {"term": {"goods.id": "g2"}},
        {"term": {"goods.id": "g3"}},
        {"term": {"goods.id": "g4"}}
      ],
      "minimum_should_match": 1
    }
  }
}

{
  "_index" : "purchase",
  "_id" : "3",
  "matched" : true,
  "explanation" : {
    "value" : 2.178501,
    "description" : "sum of:",
    "details" : [
      {
        "value" : 0.18360566,
        "description" : "weight(goods.id:g2 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      },
      {
        "value" : 0.646255,
        "description" : "weight(goods.id:g3 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      },
      {
        "value" : 1.3486402,
        "description" : "weight(goods.id:g4 in 2) [PerFieldSimilarity], result of:",
        "details" : []
      }
    ]
  }
}

五、控制子查询的打分

不管是elasticsearch自动组建子查询,还是我们自己手动构建子查询,elasticsearch都会针对每个查询做相关性的打分计算,这对于一般的语义化关键字搜索是没有问题的;

我们这里的搜索条件goods.id一般是没有任何语义的,不同的值打分应该是一样的;这样我们只能使用bool+constant_score+term来手动构建查询语句;

POST purchase/_search
{
  "query": {
    "bool": {
      "should": [
        {"constant_score": {"filter": {"term": {"goods.id": "g2"}}}},
        {"constant_score": {"filter": {"term": {"goods.id": "g3"}}}},
        {"constant_score": {"filter": {"term": {"goods.id": "g4"}}}}
      ],
      "minimum_should_match": 1
    }
  }
}


{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 3.0,
    "hits" : [
      {
        "_index" : "purchase",
        "_id" : "3",
        "_score" : 3.0,
        "_source" : {
          "id" : 3,
          "name" : "jim",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            },
            {
              "id" : "g4",
              "name" : "TV"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "2",
        "_score" : 2.0,
        "_source" : {
          "id" : 2,
          "name" : "coco",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            },
            {
              "id" : "g3",
              "name" : "ipod"
            }
          ]
        }
      },
      {
        "_index" : "purchase",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "name" : "sam",
          "goods" : [
            {
              "id" : "g1",
              "name" : "ipad"
            },
            {
              "id" : "g2",
              "name" : "iphone"
            }
          ]
        }
      }
    ]
  }
}

我们看下文档3的打分情况,每一个命中项的打分都是固定的1,最终的打分命中项的和;

POST purchase/_explain/3
{
  "query": {
    "bool": {
      "should": [
        {"constant_score": {"filter": {"term": {"goods.id": "g2"}}}},
        {"constant_score": {"filter": {"term": {"goods.id": "g3"}}}},
        {"constant_score": {"filter": {"term": {"goods.id": "g4"}}}}
      ],
      "minimum_should_match": 1
    }
  }
}

{
  "_index" : "purchase",
  "_id" : "3",
  "matched" : true,
  "explanation" : {
    "value" : 3.0,
    "description" : "sum of:",
    "details" : [
      {
        "value" : 1.0,
        "description" : "ConstantScore(goods.id:g2)",
        "details" : [ ]
      },
      {
        "value" : 1.0,
        "description" : "ConstantScore(goods.id:g3)",
        "details" : [ ]
      },
      {
        "value" : 1.0,
        "description" : "ConstantScore(goods.id:g4)",
        "details" : [ ]
      }
    ]
  }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

elasticsearch查询之keyword字段的查询打分控制 的相关文章

随机推荐

  • args在python中什么意思_Python中*args、**args到底是什么、有啥区别、怎么用

    调用函数时使用 和 假设有函数 def test a b c test args 的作用其实就是把序列 args 中的每个元素 当作位置参数传进去 比如上面这个代码 如果 args 等于 1 2 3 那么这个代码就等价于 test 1 2
  • BUUCTF-[Misc杂项]---二维码

    目录 BUUCTF Misc杂项 二维码 题目 题解 BUUCTF Misc杂项 二维码 题目 题解 下载附加压缩包并打开 打开后发现是一张png图片 解压下来 解压后是一张二维码图片 我们直接放到二维码查看器工具当中 得到此条信息 我们继
  • c# global::

    Global 表示所有命名空间的根部 Global asa 文件的作用主要是用于站点或虚拟目录下程序的数据共享和多线程 在 global asa 中 可以声明 Application 事件和 Session 事件 并可以声明一些 Sessi
  • Windows安装pip方法

    pip是一款非常方便的python包管理工具 本文主要介绍在windows 10下安装pip方法 1 下载pip 地址 https pypi python org pypi pip downloads 注意选择tar gz压缩包 目前最新版
  • 服务器系统版本选择,云服务器选择系统版本

    云服务器选择系统版本 内容精选 换一换 使用弹性云服务器或者外部镜像文件创建私有镜像时 必须确保操作系统中已安装PV driver 使新发放的云服务器支持XEN虚拟化 同时也可以提升云服务器的I O处理性能 实现对云服务器硬件的监控和其他高
  • MobileNet ShuffleNet & yolov5替换backbone

    以下内容参考参考 MobileNet V1 亮点 1 使用可分离卷积核大幅减少参数量 2 增加了超参数a b a 卷积核个数的倍率 b 分辨率高低 MobileNet V2 亮点 1 使用倒结构残差 残差结构 两边粗 中间细 倒残差结构 两
  • uniapp为page设置背景色不生效 & lang=“scss“ scoped的page样式失效,uniapp重复打开页面

    一 lang scss scoped中的page选择器的样式失效 在用uniapp生成网页和H5时有效 但生成小程序或者app时无效 这是因为page选择器在小程序和app编译中是页面的父节点 所以加上scoped限定后 会导致无法选中 详
  • 《Centos6.5——图形化安装虚拟机》

    目录 安装虚拟机以及虚拟机的配置 1 先下载镜像 2 安装VMware Workstation 3 打开vm 点击创建新的虚拟机 1 一路下一步 直到选择镜像 2 继续下一步 直到如下图 选择CD 选择镜像后点击确定 然后点击开启虚拟机 3
  • 阿里云-云存储OSS

    1 简述OSS 数据的可靠性较强 三重备份 系统的安全性较强 对称加密 签名权限控制以及防盗链功能 文件存储的容量无限 无需人工运维 部署扩容 无需规则 按需扩容 提供丰富的API接口 SDK包 客户端工具台 控制台 方便应用程序调用 安全
  • 基于Python和mysql开发的今天吃什么微信小程序(源码+数据库+程序配置说明书+程序使用说明书)

    一 项目简介 本项目是一套基于Python和mysql开发的今天吃什么微信小程序 主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者 包含 项目源码 项目文档 数据库脚本等 该项目附带全部源码可作为毕设使用 项目
  • 【深度学习】池化 (pooling)

    深度学习中 有两种实现非线性的算子 一个是激活函数 另一个就是池化 pooling 在知乎上面看到一个关于池化的神解释 摘来 池化 涨水 卷积的目的是为了得到物体的边缘形状 可以想象水要了解山立体的形状 水位低时得出山脚的形状 水位中等时得
  • 信息安全—密码学信息熵信息理论基础—熵的概念(熵、联合熵、条件熵、平均互信息)

    数学基础 概率论乘法法则 两个事件相互独立 P A B P A P B 意思是事件A和事件B同时发生的概率 事件A发生的概率 事件B发生的概率 举个栗子 掷两枚硬币硬币同时立着的概率 掷一枚硬币立着的概率 再掷一枚 硬币立着的概率 两个事件
  • Partition List

    题目 Given a linked list and a value x partition it such that all nodes less than x come before nodes greater than or equa
  • 关于免费获得WPS会员自动邀请助力的JAVA项目分享

    WPS自动邀请说明 一 基本说明 本项目不是全自动 需要用户每日13点前在微信WPS会员公众号完成在线签到 再完成签到后即可输入自己uid完成自动拉满10人的任务 本项目仅用于学习 不用于商业 二 具体步骤 添加微信公众号WPS会员 福利
  • python编程标准化_Python数据预处理:彻底理解标准化和归一化

    数据预处理 数据中不同特征的量纲可能不一致 数值间的差别可能很大 不进行处理可能会影响到数据分析的结果 因此 需要对数据按照一定比例进行缩放 使之落在一个特定的区域 便于进行综合分析 常用的方法有两种 最大 最小规范化 对原始数据进行线性变
  • go语言基础-----07-----方法

    1 方法的介绍 1 方法的概念 简单说就是一个对象里面的函数 称为方法 2 在go语言中 可以给任意自定义类型 包括内置类型 但不包括指针类型 添加相应的方法 3 方法总是绑定对象实例 并隐式将实例作为第一参数 4 方法的语法 func r
  • 数学建模常用模型简介&其他模型大全汇总

    一 预测与预报 1 灰色预测模型 必掌握 解决预测类型题目 由于属于灰箱模型 一般比赛期间 不优先 使用 满足两个条件可用 数据样本点个数少 6 15 个 数据呈现指数或曲线的形式 2 微分方程预测 高大上 备用 微分方程预测是方程类模型中
  • Python解析JSON数据的基本方法

    一 JSON数据格式介绍 JSON JavaScript Object Notation 是一种轻量级的数据交换格式 JSON建构于两种结构 json是Javascript中的对象和数组中的对象 本质上来讲就是有特定结构的字符串 所以可以通
  • Chrome 浏览器css样式不显示问题解决方法

    在eclipse里改动css 改动后刷新chrome 样式不变问题 但IE浏览器却可更新样式 刚开始以为是浏览器兼容之类的问题 后来发现是chrome会缓存css样式 按F5刷新是没用的 得清除缓存才行 更快捷的方式是按Ctrl F5强制重
  • elasticsearch查询之keyword字段的查询打分控制

    一 数据情况 purchase记录每个用户的购买信息 PUT purchase mappings properties id type keyword name type text goods properties id