Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

这篇具有很好参考价值的文章主要介绍了Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Elasticsearch实战-ES搜索如何使用In操作查询filter过滤及如何Distinct去除重复数据


场景:
  1. ES搜索, 获取手机号是 19000001111 或者 19000003333 后者 19000004444 的人, 并且 性别是男, 且 年龄是[20-30]的人,这种查询用mysql 如何实现 ? 在mysql中会用in查询, 但是在ES中 我们实现就是 terms来实现 in功能的查询
mysql查询: select * from xx where mobile in(19000001111 , 19000003333 ,19000004444) and sex=男 and age >=20 and age <=30
  1. ES搜索,现在我们公司有多少个部门,或者我们公司的人全都分布在哪些省份 , 对于这种需求查询就是去除重复数据,要对某个字段去重才能实现
mysql查询: select count(distinct (deptName)), count(distinct(provice)) from xx 
  1. ES搜索,以1000为工资单位 区间统计,每个工资段的部门的人数,要按照部门来去 去重数据,找出每个区间去重的哪些部门
1.准备数据

先构造 index:testquery, 然后构造mapping结构, 插入测试数据

#构建 库index testquer
put /testquery

#构建mapping结构
put /testquery/_mapping
{
    "properties" : {
      "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "copy_to" : [
            "info"
          ]
        },
      "age" : {
          "type" : "long"
        },
      "area" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
      "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
      "content" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
      "deptName" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "fielddata" : true
        },
      "empId" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
      "info" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
      "mobile" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "copy_to" : [
            "info"
          ]
        },
      "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "copy_to" : [
            "info"
          ]
        },
      "provice" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "fielddata" : true
        },
      "salary" : {
          "type" : "long"
        },
      "sex" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
 		 "addtime" : {
          "type":"date",
          //时间格式 epoch_millis表示毫秒
          "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
        }
    }
}

插入测试数据

put /testquery/_bulk
{"index":{"_id": 1},"addtime":"1658041203000"}
{"empId" : "111","name" : "员工1","age" : 20,"sex" : "男","mobile" : "19000001111","salary":1333,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"光谷大道","address":"湖北省武汉市洪山区光谷大厦","content" : "i like to write best elasticsearch article", "addtime":"1658140003000"}
{"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},"addtime":"1658040045600"}
{ "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},"addtime":"1658040012000"}
{"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},"addtime":"1658040593000"}
{ "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},"addtime":"1658043403000"}
{"empId" : "666","name" : "员工6","age" : 30,"sex" : "女","mobile" : "19000006666","salary":30000,"deptName" : "技术部","provice" : "武汉市","city":"湖北省","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i like java developer","addtime":"1658041003000"}
{"index":{"_id": 7}}
{"empId" : "777","name" : "员工7","age" : 60,"sex" : "女","mobile" : "19000007777","salary":52130,"deptName" : "测试部","provice" : "湖北省","city":"黄冈市","area":"边城区","address" : "湖北省黄冈市边城区","content" : "i like elasticsearch developer","addtime":"1658040008000"}
{"index":{"_id": 8}}
{"empId" : "888","name" : "员工8","age" : 19,"sex" : "女","mobile" : "19000008888","salary":60000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"汉阳区","address" : "湖北省武汉市江汉大学","content" : "i like spark language","addtime":"1656040003000"}
{"index":{"_id": 9}}
{"empId" : "999","name" : "员工9","age" : 40,"sex" : "男","mobile" : "19000009999","salary":23000,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市郑州大学","content" : "i like java developer","addtime":"1608040003000"}
{"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","addtime":"1654040003000"}
{"index":{"_id": 11}}
{"empId" : "111111","name" : "王河南","age" : 61,"sex" : "男","mobile" : "19000001011","salary":10000,"deptName" : "销售部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am not like  java ","addtime":"1658740003000"}
{"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","addtime":"165704003000"}
{"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 ","addtime":"1658140003000"}
{"index":{"_id": 14}}
{"empId" : "141414","name" : "王技术","age" : 45,"sex" : "女","mobile" : "19000001014","salary":6222,"deptName" : "测试部",,"provice" : "河南省","city":"郑州市","area":"金水区","address" : "河南省郑州市金水区","content" : "i like c++","addtime":"1656040003000"}
{"index":{"_id": 15}}
{"empId" : "151515","name" : "张测试","age" : 18,"sex" : "男","mobile" : "19000001015","salary":20000,"deptName" : "技术部",,"provice" : "河南省","city":"郑州市","area":"高新开发区","address" : "河南省郑州高新开发区","content" : "i think spark is good","addtime":"1658040003000"}
2. ES In查询 实现方式
2.1 es In查询 terms实现方式

ES搜索, 获取手机号是 19000001111 或者 19000003333 后者 19000004444 ,19000005555的人, 并且 性别是男, 且 年龄是[20-30]的人,这种查询用mysql 如何实现 ? 在mysql中会用in查询, 但是在ES中 我们实现就是 terms来实现 in功能的查询

  • 首先 terms 实现 in (19000001111 , 19000003333 ,19000004444, 19000005555 )
  • 然后且 查询 性别是男的 bool must来查询 sex
  • 然后且 查询 年龄range 在20-25之间的 使用 filter range来过滤范围
手机号 性别 年龄 是否符合
19000001111 20 符合
19000003333 30 不符合 age
19000004444 20 不符合 sex
19000005555 20 符合

使用terms来实现 in的操作, 使用 bool must 进行匹配 sex, 然后使用给filter 来过滤范围

get /testquery/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "terms": {
            "mobile.keyword": [
              "19000001111",
              "19000003333",
              "19000004444",
              "19000005555"
              
            ]
          }
        },
        {
          "match": {
            "sex": "男"
          }
        }
      ],
      //在 bool内部, must查询完的平级 进行filter过滤数据
      "filter":{
        "range": {
          "age": {
            "gte": 20,
            "lte": 25
         }
        }
      }
    }
  }
}

查询结果 2条数据, 分别是 19400001111-20岁, 19400005555-20岁,都是男生,结果正确
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

2.2 es In查询 bool should方式 单层filter

terms 其实就是对 should的简化方式,我们下面实现一种 should的方式来进行查询
使用 should 来实现 in的操作, must查询 sex 男生, 再次使用给filter 来过滤范围, 注意 should和 must结合使用的话, 一定要是先must再should,而且should 一定是再 must内部,为什么这样做, 之前的文章讲过 大家可以回顾一下
Elasticsearch实战(五)—高级搜索 Match/Match_phrase/Term/Must/should 组合使用 其中2.2章节就是 讲的 A&B&( C || D )的多种查询语法如何写

依旧是 上面的场景
ES搜索, 获取手机号是 19000001111 或者 19000003333 后者 19000004444 ,19000005555的人, 并且 性别是男, 且 年龄是[20-30]的人,通过 bool should 及单层 filter 实现

#先must 查询 ,然后 再 must内部 should查询, 然后 对结果进行 filter range 年龄20-25岁的

get /testquery/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "sex": "男"
          }
        },
        //注意大括号, 再must 内部 再来一次should 来进行 或操作
        {
          "bool":{
            "should": [
             {
              "match": {
                 "mobile.keyword": "19000001111"
               }
            },
             {
              "match": {
                "mobile.keyword": "19000003333"
               }
            },
             {
                "match": {
                 "mobile.keyword": "19000004444"
                }
             },
              {
              "match": {
                 "mobile.keyword": "19000005555"
               }
             }
           ]
          }
        }
      ]
      //must 同级 ,对查询的结果过滤, 保留年龄 20-25的
      ,"filter": [
        {
          "range": {
            "age": {
              "gte": 20,
              "lte": 25
            }
          }
        }
      ]
    }
  }
}

查询结果 2条数据, 分别是 19400001111-20岁, 19400005555-20岁,都是男生,结果正确
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

那如果再一个条件呢? 比如 现在是过滤 年龄是 20-25之间的, 我们现在 加一个 部门是技术部的 ,如何实现 ?

2.3 es In查询 bool should方式 多个filter过滤使用

filter 过滤可以有多层过滤条件, 比如刚才的 我们使用给filter range 过滤了 age在20-25之间的, 我们如果再加一个 部门的过滤呢?
当然 部门的过滤我们可以 在 match sex:男 中加一个条件 deptName:技术部, 如果我们像过滤工资呢? 过滤工资 大于5000的人
这就涉及多个filter 的使用了

使用 must 多个嵌套, 单层filter实现

  • must sex:男,
  • must deptName:技术部
  • 手机号 should (19000001111 , 19000003333 ,19000004444, 19000005555 )
  • 然后且 查询 年龄range 在20-25之间的 使用 filter range来过滤范围
#先must 查询多个 以下 ,然后 再 must内部 should查询, 然后 对结果进行 filter range 年龄20-25岁的
get /testquery/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "sex": "男"
          }
        },
        {
          "match": {
            "deptName.keyword": "技术部"
          }
        },
        //must 内部 开始should 判断手机号
        {
          "bool": {
            "should": [
              {
              "match": {
                  "mobile.keyword": "19000001111"
                }
              },
              {
                "match": {
                  "mobile.keyword": "19000003333"
                }
              },
              {
                "match": {
                  "mobile.keyword": "19000004444"
                }
              },
              {
                "match": {
                  "mobile.keyword": "19000005555"
                }
              }
            ]
          }
        }
      ]
      //must 同级 开始 filter
      , "filter": [
        {
          "range": {
            "age": {
              "gte": 20,
              "lte": 25
            }
          }
        }
      ]
    }
  }
}

先must 查询 sex:男, deptName:技术部, 然后 再 must内部 should查询 mobile in (19400001111,19400003333,19400004444,19400005555)
然后 对结果进行 filter range 年龄20-25岁的

查询结果 1条数据, 分别是 19400001111-20岁,男生,结果正确
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

那如果使用多层filter 呢 ? 如何实现 ?
那如果使用多层filter 呢 ? 如何实现 ?
那如果使用多层filter 呢 ? 如何实现 ?

我们 已经是 must, terms in 结构, 然后 filter 这次 多加一些条件 比如 range age 20-30的,是技术部的 放在filter中操作
使用 must 单个条件, 多层filter 过滤实现

  • must sex:男,
  • must deptName:技术部
  • 手机号 should (19000001111 , 19000003333 ,19000004444, 19000005555 )
  • 然后且 查询 年龄range 在20-25之间的 使用 filter range来过滤范围
get /testquery/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "sex": "男"
          }
        },
        {
          "terms": {
            "mobile": [
              "19000001111",
              "19000003333",
              "19000004444",
              "19000005555"
            ]
          }
        }
      ]
      //must 同级 filter
      ,"filter": [
        {
          "range": {
            "age": {
              "gte": 20,
              "lte": 25
            }
          }
        },
        {
          "term": {
            "deptName.keyword": "技术部"
          }
        }
      ]
    }
  }
}

多层filter 过滤条件 过滤age, 过滤 deptName, 查询结果 1条数据, 分别是 19400001111-20岁,男生,结果正确
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

3.查询数据去重 caidinality
3.1 去重统计公司 技术部有多少人 以empId为去重字段

我们要想精确查 技术部有多少人,肯定要以某个字段去除重复数据的

#mysql 语法 统计技术部有多少人, 以 employeeid为唯一标识,去重重复数据
select count(dinstinct (employee_id)) from xx where deptName="技术部"

ES中 通过 caidinality 来实现去除重复数据,使用在 aggs中 聚合操作去除重复数据

# caidinality 去除重复数据, 使用在 aggs中 聚合操作去除重复数据
get /testquery/_search
{
  "query":{
    "match": {
      "deptName.keyword": "技术部"
    }
  },
  "aggs":{
    "count_emp":{
     "cardinality": {
       "field": "empId.keyword"
     }
    }
  }
}


查询过滤 结果 技术部的人 一共有四个, 去除重复数据 count_emp 就是 4人
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据

3.1 以月为区间,去重caidinality 统计每月 有多少个员工入职

场景 :

  • 比如要统计每月 销售量> 5 的汽车品牌
    那就是 date_hisgogram 时间区间按月统计,参数 min_doc_count:5 然后对 汽车的品牌 name进行去重统计
  • 比如 要统计每月 公司部门 入职人数>1的部门名称
    那就是 date_hisgogram 时间区间按月统计,参数 min_doc_count:1 然后对 部门的名称 deptName进行去重统计

先把 empId设为 fileld_data=true 才能用做聚合 去重操作, 注意fielddata不建议在生产中用,后面篇章我们会介绍为什么不建议用,会导致OOM 内存溢出, 先暂时这样用,方便做测试数据

PUT testquery/_mapping
{
  "properties": {
    "empId": { 
      "type":     "text",
      "fielddata": true
    }
  }
}

统计每月 公司部门 去重后的入职人数>1的部门名称

# 要统计每月 公司部门 入职人数>1 的部门名称
get /testquery/_search
{
  "size":0,
  //每月 统计结果人数 超过2人的
  "aggs":{
    "group_as_month":{
      "date_histogram": {
        //以入职时间 进行区间统计
        "field": "addtime",
        "calendar_interval": "month",
        "min_doc_count": 1
      }
      //分组名称group_as_month内 date_histogram 同级别以 empid去重统计
      , "aggs": {
        "count_emp": {
          "cardinality": {
            "field": "empId"
          }
        }
      }
    }
  }
}

查询过滤 结果 结果正确, 12月,5月,6月 入职1人, 7月 入职4人, 这里的统计人数的经过数据去重的 caidinality实现的 emp员工id去重
Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据


至此 我们已经学习了 ES 如何使用in查询数据,及 filter 单层,多层过滤如何查询,还有就是如果要实现distinct 去重统计,就要使用 caidinality来进行去重操作文章来源地址https://www.toymoban.com/news/detail-406519.html

到了这里,关于Elasticsearch实战(十七)---ES搜索如何使用In操作查询及如何Distinct去除重复数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查

            本篇是这个系列的最后一篇了,在这之前可以先看看前面的内容: ES搜索引擎入门+最佳实践(一)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(二)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(三)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(四)_flame.liu的博客

    2024年02月12日
    浏览(42)
  • Java SpringBoot API 实现ES(Elasticsearch)搜索引擎的一系列操作(超详细)(模拟数据库操作)

    小编使用的是elasticsearch-7.3.2 基础说明: 启动:进入elasticsearch-7.3.2/bin目录,双击elasticsearch.bat进行启动,当出现一下界面说明,启动成功。也可以访问http://localhost:9200/ 启动ES管理:进入elasticsearch-head-master文件夹,然后进入cmd命令界面,输入npm run start 即可启动。访问http

    2024年02月04日
    浏览(44)
  • Elasticsearch连续剧之实战篇Java操作es

    作者:狮子也疯狂 专栏:《es》 坚持做好每一步,幸运之神自然会驾凌在你的身上 大家好!我是狮子,在上几篇文章中,详细介绍了在kibana中操作es,现在我们来看看真实开发中,如何使用Java操作es。 咱们先来了解一下,原生Java操作ES api接口,但是原生Java操作es的索引和文

    2023年04月15日
    浏览(30)
  • elasticsearch[五]:深入探索ES搜索引擎的自动补全与拼写纠错:如何实现高效智能的搜索体验

    前一章讲了搜索中的拼写纠错功能,里面一个很重要的概念就是莱文斯坦距离。这章会讲解搜索中提升用户体验的另一项功能 - [自动补全]。本章直接介绍 ES 中的实现方式以及真正的搜索引擎对自动补全功能的优化。 大家对上面的这个应该都不陌生,搜索引擎会根据你输入的

    2024年01月24日
    浏览(40)
  • 【Elasticsearch】小白实战!ES使用Reindex迁移数据

    文章有点长,如果你想认真阅读,建议到我语雀文档上观看,格式友好 - ES 迁移工作 最近有一个需求是需要我负责将服务器A里的 ES 数据迁移到服务器B上,但是由于环境不通,所以就先在公司的测试环境和我本地上进行测试,因为之前没有接触过 ES 数据的迁移,所以上手时

    2024年02月05日
    浏览(27)
  • 项目中使用es(一):使用springboot操作elasticsearch

    写在前面 对于elasticsearch的搭建,前面写了一篇文章有简单描述如何搭建es,本次主要介绍如何在项目里使用,主要使用ElasticsearchRepository和ElasticsearchRestTemplate操作es。 搭建项目环境和选择合适版本 首先选择合适的项目组件版本,因为es版本和springboot版本有对应,如果不合适会

    2024年02月08日
    浏览(28)
  • 项目中使用es(二):使用RestHighLevelClient操作elasticsearch

    写在前面 之前写了有关elasticsearch的搭建和使用springboot操作elasticsearch,这次主要简单说下使用RestHighLevelClient工具包操作es。 搭建环境和选择合适的版本 环境还是以springboot2.7.12为基础搭建的,不过这不重要,因为这次想说的是RestHighLevelClient操作elasticsearch,RestHighLevelClient版本

    2024年02月14日
    浏览(30)
  • Elasticsearch学习3-使用RestClient操作es

    JavaREST客户端有两种模式: Java Low Level REST Client:ES官方的低级客户端。低级别的客户端通过http与Elasticearch集群通信。 Java High Level REST Client:ES官方的高级客户端。基于上面的低级客户端,也是通过HTTP与ES集群进行通信。它提供了更多的接口。 此外Spring也对RestClient进行了封装

    2024年02月11日
    浏览(35)
  • 使用postman和es插件操作elasticsearch API

    本文介绍了使用postman和es浏览器插件操作elasticsearch API的常用方法 本文使用的es浏览器插件时edge下的elasticvue,可以在edge的应用商店直接搜索安装,相较于es-head,这个插件一直在维护更新,使用还是很方便的     查看索引 查看索引主要使用get方法,可以查看单个or多个索引,

    2024年02月07日
    浏览(27)
  • 【Elasticsearch】使用Python完成对ES的插入操作

    1.Python搭建Flask服务,编写ES脚本。 2.通过Java调用Python接口,完成对ES的插入操作。 Elasticsearch 7.16.0 ESObject是一个模板,其中有很多其他的函数。通过Java调用,还可以实现很多操作,如删除、查询等。

    2024年02月15日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包