es中的term和match的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了es中的term和match的区别相关的知识,希望对你有一定的参考价值。

参考技术A 在实际的项目查询中, term 和 match 是最常用的两个查询,而经常搞不清两者有什么区别,趁机总结有空总结下。

先看看term的定义,term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解。

这里通过例子来说明,先存放一些数据:

来使用 term 查询下:

结果是,上面的两条数据都能查询到:

发现,title里有关love的关键字都查出来了,但是我只想精确匹配 love China 这个,按照下面的写法看看能不能查出来:

执行发现无数据,从概念上看,term属于精确匹配,只能查单个词。我想用term匹配多个词怎么做?可以使用 terms 来:

查询结果为:

发现全部查询出来,为什么?因为terms里的 [ ] 多个是或者的关系,只要满足其中一个词就可以。想要通知满足两个词的话,就得使用bool的must来做,如下:

可以看到,我们上面使用 china 是小写的。当使用的是大写的 China 我们进行搜索的时候,发现搜不到任何信息。这是为什么了?title这个词在进行存储的时候,进行了分词处理。我们这里使用的是默认的分词处理器进行了分词处理。我们可以看看如何进行分词处理的?

结果为:

分析出来的为 love 和 china 的两个词。而 term 只能完完整整的匹配上面的词,不做任何改变的匹配。所以,我们使用 China 这样的方式进行的查询的时候,就会失败。稍后会有一节专门讲解分词器。

先用 love China 来匹配。

结果是:

发现两个都查出来了,为什么?因为match进行搜索的时候,会先进行分词拆分,拆完后,再来匹配,上面两个内容,他们title的词条为: love china hubei ,我们搜索的为 love China 我们进行分词处理得到为 love china ,并且属于或的关系,只要任何一个词条在里面就能匹配到。如果想 love 和 China 同时匹配到的话,怎么做?使用 match_phrase

match_phrase 称为短语搜索,要求所有的分词必须同时出现在文档中,同时位置必须紧邻一致。

结果为:

这次好像符合我们的需求了,结果只出现了一条记录。

git,es的基本查询,组合查询,mapping映射,i分词,term和match

git

# 1 你们公司用的github,码云,还是gitlab?
# 2 公司用github?
# 3 协同开发,要上远程仓库(github,码云,还是gitlab)
# 4 中小型公司,放到码云上,公司没有实力搭一个gitlab,相关技术人员,自己没有服务器
# 5 你们公司,写了一个价值1千万的项目,那把它放到码云上,公司放心吗?第三方
# 6 自己搭git仓库,gitlab,免费开源的git仓库,公司自己服务器,

# 7 刚开始用svn,用git,bitbucket,一个仓库不能超过2g,ios那边

# 8 禅道,自己自有的,协同管理平台
# 9 你写好代码,提到git上,新员工,公司1kw的项目,敢不敢信任你的代码,有人去给你看,

# 10 项目已经写好了,测试人测出bug来了,在协同管理平台提交bug,----》上级领导---》看到它提的bug----》转给你----》最显眼的位置,---》正在解决(变绿)---》点已解决---》测试那看到了---》



# 11 你在开发中,遇到冲突怎么办?
	-两种情况会出现冲突:
  	-多个人在同一个分支上开发,两个人改了同一行代码,先提交的人没问题,后提交的会出冲突
    -合并分支的时候出现冲突
    
 # 12 pycharm实操冲突及解决(大部分都不用命令,pycharm点点点)
用两个账号,这两个问题都重现一下(在码云上)

# 你的代码多久提交一次---》一个功能写完了,测着没问题提交一下,都个人用同一个分支开发,你要时不时的pull---》

2 es基本查询

# 1 排序
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
   "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}
# 升序
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
   "sort": [
    {
      "age": {
        "order": "asc"
      }
    }
  ]
}

# 并不是所有类型都支持排序(只允许数字类型做排序)
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
   "sort": [
    {
      "name": {
        "order": "asc"
      }
    }
  ]
}
# match和match_all的区别?
mach表示要查询,根据字段查,match_all查所有
GET lqz/doc/_search
{
  "query": {
    "match_all": {}
  }
}

#2 分页
GET lqz/doc/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ], 
  "from": 2,
  "size": 1
}
#   "from": 2,代表从第二条开始, 取一条"size": 1

# 有了这个查询,如何分页?
一页有10条数据
第一页:
  "from": 0,
  "size": 10
第二页:
  "from": 10,
  "size": 10
第三页:
  "from": 20,
  "size": 10

3 es 组合查询

# 多个条件,and ,or ,not
# 对到es中就是布尔查询,must,should,must_not,filter

# 1 组合查询之must
# 查询form gu和age=30的数据
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "age": "30"
          }
        }
      ]
    }
  }
}
# 查询form gu数据()
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        }
      ]
    }
  }
}
# 同上
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  }
}

# 2 组合查询之should,或者的条件
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "tags": "闭月"
          }
        }
      ]
    }
  }
}
# 3 组合查询之must_not  取反
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "tags": "可爱"
          }
        },
        {
          "match": {
            "age": 18
          }
        }
      ]
    }
  }
}
# `filter`条件过滤查询,过滤条件的范围用`range`表示,`gt`表示大于,大于多少呢
# gt:大于   lt:小于  get:大于等于   let:小于等于
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        }
      ],
      "filter": {
        "range": {
          "age": {
            "gt": 25
          }
        }
      }
    }
  }
}
# 查询年龄小于等于18的所有数据
GET lqz/doc/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "age": {
            "lte": 18
          }
        }
      }
    }
  }
}
# 2 对结果进行过滤,类似于如下
select * from user;
select name,age from user;
# 对应到es的查询
GET lqz/doc/_search
{
  "query": {
    "match": {
      "name": "顾老二"
    }
  },
  "_source": ["name", "age"]
}
# 3 结果高亮显示(默认情况)
GET lqz/doc/_search
{
  "query": {
    "match": {
      "name": "石头"
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}
# 定制高亮显示的样式
GET lqz/chengyuan/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "highlight": {
    "pre_tags": "<b class=‘key‘ style=‘color:red‘>",
    "post_tags": "</b>",
    "fields": {
      "from": {}
    }
  }
}
# 总结:
	混合开发,你知道怎么处理
  前后端分离,你怎么处理?<b class=‘key‘ style=‘color:red‘>串直接以josn格式返回,前端自行渲染
			
    
 # 用的最多就是match+布尔+高亮+分页
# 聚合查询
# 1 聚合查询之avg
select max(age) as my_avg from user;
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "aggs": {
    "my_avg": {
      "avg": {
        "field": "age"
      }
    }
  },
  "_source": ["name", "age"]
}
# 2 聚合查询之max,size=0表示不取数据,只要max的结果
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "aggs": {
    "my_max": {
      "max": {
        "field": "age"
      }
    }
  },
  "size": 0
}
# 3 聚合之min
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "aggs": {
    "my_min": {
      "min": {
        "field": "age"
      }
    }
  },
  "size": 0
}
# 4 聚合查询之sum
GET lqz/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "aggs": {
    "my_sum": {
      "sum": {
        "field": "age"
      }
    }
  },
  "size": 0
}

# 5 聚合之分组
GET lqz/doc/_search
{
  "size": 0, 
  "query": {
    "match_all": {}
  },
  "aggs": {
    "age_group": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 15,
            "to": 20
          },
          {
            "from": 20,
            "to": 25
          },
          {
            "from": 25,
            "to": 30
          }
        ]
      }
    }
  }
}

4 mapping介绍

# 查看索引信息---》mapping字典---》映射(类型,表类型,表结构)
GET lqz
# 6.x以后一个索引只能有一个映射类型(只能有一个表)
# 创建映射
# 创建索引,并设置映射
PUT books
{
  "mappings": {
    "properties":{
      "title":{
        "type":"text",
        "analyzer": "ik_max_word"
      },
      "price":{
        "type":"integer"
      },
      "addr":{
        "type":"keyword"
      },
      "company":{
        "properties":{
          "name":{"type":"text"},
          "company_addr":{"type":"text"},
          "employee_count":{"type":"integer"}
        }
      },
      "publish_date":{"type":"date","format":"yyy-MM-dd"}
      
    }
    
  }
}
# 插入测试数据
PUT books/_doc/1
{
  "title":"大头儿子小偷爸爸",
  "price":100,  
  "addr":"北京天安门",
  "company":{
    "name":"我爱北京天安门",
    "company_addr":"我的家在东北松花江傻姑娘",
    "employee_count":10
  },
  "publish_date":"2019-08-19"
}

PUT books/_doc/2
{
  "title":"白雪公主和十个小矮人",
  "price":"99",
  "addr":"黑暗森里",
  "company":{
    "name":"我的家乡在上海",
    "company_addr":"朋友一生一起走",
    "employee_count":10
  },
  "publish_date":"2018-05-19"
}

PUT books/_doc/3
{
  "title":"白雪公主和十个小矮人",
  "price":"99",
  "addr":"黑暗森里",
  "age":18
}
# 查看映射
GET books
GET books/_mapping

# 映射是什么?映射有什么用?  规定了表结构(不是强制的),规定了哪个字段是可以用来全文检索,是否是数字类型,布尔类型
# mapping类型一旦确定,以后就不能修改了,但是可以插入字段

5 ik分词

技术图片

# 全文检索,有了映射,决定了我可以对某个字段做全文检索
# es默认分词对英文友好,使用中文分词器(es的插件),ik(作者,中国人,elasticsearch开源社区负责人)

# 是es的一个插件(es如何安装插件)
	- 第一种:命令行(内置插件)
  	bin/elasticsearch-plugin install analysis-smartcn  安装中文分词器
  -第二种:url安装(第三方插件)
  	bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
  -第三种:手动安装(推荐用)
  	-下载,解压到es的plugins路径下,重启es即可
    -注意:ik分词器跟es版本一定要对应
    
# 两种分词方式
  # ik_smart:分词分的
  # ik_max_word :分词分的多
  
  # ik_smart分的词少,粒度大
  GET _analyze
  {
    "analyzer": "ik_smart",
    "text": "上海自来水来自海上"
  }
  # ik_smart分的词多,粒度小
  GET _analyze
  {
    "analyzer": "ik_max_word",
    "text": "上海自来水来自海上"
  }
  
# 在创建映射的时候配置
# 以后你的操作:
	-文章标题:ik_max_word
  -文章内容:ik_smart
  -摘要
  -作者
  -创建时间


6 term和match的区别

# match:我们今天出去玩 ----》分词---》按分词去搜
#term:我们今天出去玩---》直接拿着[我们今天出去玩]--->去索引中查询



# 查不到内容,直接拿着  Python爬虫 去查,因为没有索引,所以查不到
GET books/_search
{
  "query":{
    "term":{
      "title":"Python爬虫"
    }
  }
}
# 能查到,而且带python的都查出来了
# Python   爬虫  分了词,分别拿着这两个词去查,带python关键字,带爬虫关键字都能查到
GET books/_search
{
  "query":{
    "match":{
      "title":"Python爬虫"
    }
  }
}

以上是关于es中的term和match的区别的主要内容,如果未能解决你的问题,请参考以下文章

es match和term的区别

es查询term,match,match_phase,query_string的区别

[ES]搜索match_phrase和wildcard的区别

ES文档级查询匹配限制

商城项目17_es的DSL特定语言matchbooltermtermsaggsfromsizerangesort排序查询高亮显示

商城项目17_es的DSL特定语言matchbooltermtermsaggsfromsizerangesort排序查询高亮显示