es(4)---查询条件match和term_es match term-CSDN博客
参考文章如上。开始学习
1.text和keyword的学习
直接上官网Text type family | Elasticsearch Guide [7.17] | Elastic
Text type family
The text family includes the following field types:
- text, the traditional field type for full-text content such as the body of an email or the description of a product.
- match_only_text, a space-optimized variant of
text
that disables scoring and performs slower on queries that need positions. It is best suited for indexing log messages.服了。这里说text这个类型可以在细分未text和match_only_text
text是用来作为邮件或者是产品说明类型的数据类型
match_only_text是一种空间优化的文本变体,没有相似分数,在需要位置的查询上执行速度较慢。它最适合为日志消息建立索引。
这里简单的来说就是text字段类型为什么适用于 邮件/产品说明书呢?因为他们是可以被分析的,也就是说一大段文字可以被拆分为很多小段,text字段类型一般也不用排序和聚合。举个例子,我们的邮箱只会根据时间或者收件人去排序,什么时候根据邮件内容去排序了,如果根据内容去排序,这毫无意义。
text字段是无结构化的,但是人类能够读懂给的文字,如果你需要对【机器生成的文字内容】索引,参考【mapping unstructured content】一般人都不用不到,暂时不学。
如果你需要索引 邮件地址,域名,状态码,标签,这种最好还是用keyword。因为这种比较简单。
直接上案例。如何创建一个text字段的index
PUT my-index-000001
{
"mappings": {
"properties": {
"full_name": {
"type": "text"
}
}
}
}
-- 这个太简单了。。
开始上难度
使用一个复合类型。也就是说同时具有text和 keyword的共性。
比如某个字段,我要求可以模糊匹配,也要求可以排序和聚合
复合字段的案例
PUT my-index-000001
{
"mappings": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
-- 注意这里是什么意思呢? 就是说city字段是用text存的,city.raw使用keyword存的
PUT my-index-000001/_doc/1
{
"city": "New York"
}
-- 这里city text存了new york 方便模糊查询, city.raw存了New York方便精确查询或排序聚合
PUT my-index-000001/_doc/2
{
"city": "York"
}
GET my-index-000001/_search
{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}
--有兴趣的自己尝试
GET my-index-000001/_analyze
{
"field": "city",
"text": ["New York"]
}
GET my-index-000001/_analyze
{
"field": "city.raw",
"text": ["New York"]
}
以前如果就是keyword 或者text 后面也可以通过update mappings去更改 先暂时不看了。
Update mapping API | Elasticsearch Guide [7.17] | Elastic
复合字段带有符合分析器
我上面小小的分析了下,没想到官网很贴心,也给了案例,继续学习
Multi-fields with multiple analyzers
多字段的另一个用例是以不同的方式分析同一字段以获得更好的相关性。例如,我们可以用标准分析器对一个字段进行索引,该分析器将文本分解为单词,也可以用英语分析器将单词转换为词根形式:
简单的来说,就是对同一个字段采取不同的维度去分析。
PUT my-index-000001
{
"mappings": {
"properties": {
"text": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}
PUT my-index-000001/_doc/1
{ "text": "quick brown fox" }
PUT my-index-000001/_doc/2
{ "text": "quick brown foxes" }
GET my-index-000001/_search
{
"query": {
"multi_match": {
"query": "quick brown foxes",
"fields": [
"text",
"text.english"
],
"type": "most_fields"
}
}
}
查询结果如下,可以发现我 "query": "quick brown foxes",
这里说明了 text的是标准分词器,text.english是英语分词器,这两个doc 一个是fox一个foxes
查询的时候是根据text和text.english两个字段组成分数。
text字段 里面存的是[fox,foxes]
text.englist里面存的[fox,fox] 因为foxes本身就是fox,
虽然我们查询的两个字段都是foxes,但是在text字段是根据foxes去查询,在text.english字段是根据fox去查询。
还是analysis下
GET my-index-000001/_analyze
{
"field": "text.english",
"text": ["quick brown foxes"]
}
发现结果foxes被存储为 fox
text顾名思义是文本,也就是说只在乎数据本身,不会在乎数据的大小写。比如我存CC LOVE ZBF,text的存储会存cc love zbf
keyword顾名思义是关键词,也就是说我要找到某条数据只能通过关键词来找,可以看作mysql的自增id
下面学习下match和term的查询区别
2. match和term的区别
- match会进行分词,将分词后的field去倒排索引寻找文档;
- term不会进行分词,将原始的field去倒排索引中寻找文档
2.1数据准备
PUT test_match/_mapping
{
"properties":{
"text_name":{
"type":"text"
},
"key_name":{
"type":"keyword"
}
}
}
get test_match/_mapping
批量插入数据
POST _bulk
{"create":{"_index":"test_match","_type":"_doc"}}
{"text_name":"JAVA BOOK","key_name":"JAVA BOOK"}
{"create":{"_index":"test_match","_type":"_doc"}}
{"text_name":"ES BOOK","key_name":"ES BOOK"}
{"create":{"_index":"test_match","_type":"_doc"}}
{"text_name":"spring","key_name":"spring"}
2.2 倒排索引存储的值
2.2.1数据类型为text
GET test_match/_analyze
{
"field": "text_name",
"text": ["JAVA BOOK "]
}
数据被小写,然后分词存放
2.2.1数据类型为keyword
GET test_match/_analyze
{
"field": "key_name",
"text": ["JAVA BOOK"]
}
数据直接被存放,没经过任何处理
2.3 使用term查询text类型(不推荐)
使用term查询时,查询条件不会进行分词。但是text
类型的数据,在倒排索引中实际存储的是分词的数据。
例如term 查询text_name :JAVA BOOK,但是text_name存放的是[java/ book] 所以查询不到结果
get test_match/_search
{
"query":{
"term": {
"text_name": {
"value": "JAVA BOOK"
}
}
}
}
-- 备注这里使用小写 java book也查不到
get test_match/_search
{
"query":{
"term": {
"text_name": {
"value": "java"
}
}
}
}
-- term 查询text字段的 小写分词可以查到 比如查java,因为text_name底层存放"JAVA BOOK"这一个词的时候,将其分为"java"和"book",所以查询java的时候也是命中了索引
想要查"JAVA BOOK"这条数据 查询条件只能是"java" "book"这两条数据
2.4 term查询keyword等类型的数据
term去查询keyword的数据,均不会进行分词,但是需要注意大小写
get test_match/_search
{
"query":{
"term": {
"key_name": {
"value": "JAVA BOOK"
}
}
}
}
想要查JAVA BOOK这条数据 value只能是"JAVA BOOK"
2.5 match查询text类型(默认是or操作)
get test_match/_search
{
"query":{
"match": {
"text_name": "JAVA"
}
}
}
想要查"JAVA BOOK"这条数据,查询条件可以是"JAVA","BOOK" ,"java","book","java book","java 123456","JAVA 13456999" 等等等
2.6 match的and操作
2.5中查询默认是or操作,比如match查询text_name:"JAVA 12345"首先会将"JAVA 12345"分词为"java","12345"然后在与doc的倒排索引去比对,类似sql中的 select * from table where text_name like '%java%'or text_name like '%12345%'
有时候需要and操作 ,这个就是类似于 select * from table where text_name like '%java%' andtext_name like '%12345%'
GET test_match/_search
{
"query": {
"match": {
"text_name":{
"query": "JAVa book",
"operator": "and"
}
}
}
}
-- 新增数据
POST test_match/_doc
{
"text_name":"JAVA AND NET BOOK",
"key_name":"net"
}
注意这样会匹配到原始数据是"JAVA BOOK" 也可以匹配到 "JAVA 12345 BOOK 456"
2.7 match查询keyword类型
match查询keyword操作时,等效term
get test_match/_search
{
"query":{
"match": {
"key_name": "JAVA BOOK"
}
}
}
想要查找JAVA BOOK,只能通过"JAVA BOOK"
其实这里有点绕了。简单点来看我们先看查询的字段是什么类型text还是keyword
如果是keyword 那么我们查询条件match或term都是一样的
如果是text 那么我们需要人工的思考下 这个条件被分词小写后是什么?
然后我们看查询条件是match 还是term
如果是term就是 column=?
如果是match就思考下原先的数据是否包含了查询条件(原始数据分词后是否包含查询字段的分词)
3. match的底层转换
当match查询text类型时,在底层将会被转换为term操作。
get test_match/_search
{
"query":{
"match": {
"text_name": "JAVA BOOK"
}
}
}
被转化为
GET test_match/_search
{
"query": {
"bool": {
"should": [
{"term": {
"text_name": {
"value": "java"
}
}},
{
"term": {
"text_name": {
"value": "book"
}
}
}
]
}
}
}
也就是说通过term查询小写分词后的数据,满足任一一个分词即可。