【ES 笔记】 ElasticSearch 基本的查询语句介绍

ElasticSearch


如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里

  • 基本概念
    • ElasticSearch 是什么?
  • 搜索与过滤
    • 搜索与过滤的区别
  • 全文检索 (full text queries)
    • intervals query
    • match
    • match_bool_prefix query
    • match_phrase query
    • match_phrase_prefix query
    • multi_match query
  • 结构化查询 (term-level queries)
    • ids
    • term
    • terms
    • fuzzy
    • range
    • exists
    • prefix
    • wildcard
    • regexp
  • 时间类转换实践
    • bool query
    • boosting query
    • constant score query
    • dis max query
    • function score query

基本概念


ElasticSearch 是什么?

elasticsearch 是分布式的 “搜索引擎” 和 “数据分析引擎”

  • 搜索:站内搜索,信息检索
  • 数据分析:最近 7 天面包商品销量排名前 10 的商家有哪些?最近 1 个月访问量排名前三的新闻板块是哪些?

搜索与过滤


搜索与过滤

query context

  • 查询需要计算分数

filter context

  • 过滤只有 yes or no, 没有分数

区别

  • 过滤器和查询类似 ,但是它们在评分机制和搜索行为的性能上有所不同,过滤器不像查询会为特定的词条计算得分,搜索的过滤器只是为 ”文档是否匹配这个查询“, 返回简单的 ”是“ 或 ”否“ 的答案
  • 所以过滤器比普通的查询要快

Query and filter context


结构化查询 (term-level queries)

term-level 查询操作的是存储在反向索引(倒排索引)中的准确词根,这些查询通常用于结构化数据,如数字、日期和枚举,而不是全文字段,无需进行分析

ids

id 数组查询

{
  "query": {
    "ids" : {
      "values" : ["25328953660256334", "25328902598785991", "100"]
    }
  }
}
Term

查找包含指定字段中精确匹配查询字符串的文档

{
  "query": {
    "term": {
      "songName.keyword": {
        "value": "7k - Ao Vivo",
        "boost": 1.0
      }
    }
  }
}

精确匹配,只能搜索到 songName = “7k - Ao Vivo”, 多一点,少一点都凉凉

Terms

查询包含指定字段中包含查询词根集合中任意一个精确匹配的文档

{
  "query": {
    "terms": {
      "songName.keyword": [
      	{"value": "7k - Ao Vivo","boost": 1.0},
				{"value": "7k","boost": 1.0}
      ]
    }
  }
}
Fuzzy

模糊查询 Quem Mandou Chamar

{
	"query": {
    "fuzzy": {
      "songName.keyword": {
        "value": "Quem Mondou Chamer", # Mondou 错误,Chamer 错误
        "fuzziness": "AUTO",
        "max_expansions": 50,
        "prefix_length": 0,
        "transpositions": true
      }
    }
  }
}
Range

范围查询, 针对数值,日期,地理位置类型,可以使用范围查询

{
  "query": {
    "range": {
      "age": {
        "gte": 10,
        "lte": 20,
        "boost": 2.0
      }
    }
  }
}
Exists

存在改字段的数据,会查询出存在 songName 字段的所有数据

{
  "query": {
    "exists": {
      	"field": "songName"
    }
  }
}

有几种情况,即使有该字段,也查询不到

  • 字段数据为空数组 [] 或为 null
  • 字段 mapping 设置了 index: false
  • 数据长度超过了字段设置的长度 ignore_above
  • 字段数据格式错误,被置为 ignore_malformed
Prefix

前缀查询, 查找以 7k 为前缀的数据

{
  "query": {
    "prefix": {
      	"songName": "7k"
     }
  }
}
Wildcard

通配符查询

{
  "query": {
    "wildcard": {
      "songName": {
        "value": "7?",
        "boost": 1.0
      }
    }
  }
}
  • ? 匹配任意一个字符
  • * 匹配 0 或任意个字符,包括空
Regexp

正则查询…


复合查询 (compound queries)
1. Bool Query

布尔查询

布尔过滤器,我们就可以类似理解 SQL 的 where 语句, 可以由四种子句组成,子句之间的关系是 AND, 满足所有的子句的要求才是 true ,才是符合条件的查询结果

{
   "bool" : {
      "must" :     [],
      "filter":    [],
      "should" :   [],
      "must_not" : []
   }
}
  • must 所有子句都必须要匹配,与 AND 且等价,与 score 相关
  • filter 所有子句都必须匹配, 但是属于 filter context, 不属于 query context,所以在 filter 下的查询,是没有分数的,是与 score 不相关的
  • must_not 所有子句都不能匹配,与 NOT 非等价
  • should 至少一个子句要匹配,与 OR 等价
  • boost 参数可以修改特定子句的权重比例,默认是 1.0, 如果是 2.0 的话,就代表该子句的 score 原值的两倍

Example

  • term 查询歌手为 Luiz De Carvalho 且歌名大概为 De Joelhos 的歌曲
{
	"query": {
		"bool": {
			"must": [
				{"term": {"artistNames.keyword": "Luiz De Carvalho"}},
				{"match": {"songName": "De Joelhos"}}
			]
		}
	}
}
{
    "took": 15,
    "timed_out": false,
    "_shards": {
        "total": 6,
        "successful": 6,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 33,
            "relation": "eq"
        },
        "max_score": 15.077974,
        "hits": [
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25335347327064482",
                "_score": 15.077974,
                "_source": {
                    "id": 25335347327064482,
                    "externalSongId": "spotify-3SeY1xxKaUR0I46wDmJN1Z",
                    "songName": "De Joelhos",
                    "artistNames": [
                        "Luiz De Carvalho"
                    ],
                    "albumName": "Meus Hinos Queridos, Vol. 3",
                    "albumId": 25335347325421019,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e02c7039f96c75d897f62e76331",
                    "duration": 155,
                    "source": "YOUTUBE",
                    "externalId": "youtube-QO4y0G2M0m4",
                    "playUrl": "https://www.youtube.com/watch?v=QO4y0G2M0m4",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            },
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25335347327283747",
                "_score": 13.863211,
                "_source": {
                    "id": 25335347327283747,
                    "externalSongId": "spotify-0wTcgBVW9IbpgeUt1GCWC3",
                    "songName": "De Joelhos (Instrumental)",
                    "artistNames": [
                        "Luiz De Carvalho"
                    ],
                    "albumName": "Meus Hinos Queridos, Vol. 3",
                    "albumId": 25335347325421019,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e02c7039f96c75d897f62e76331",
                    "duration": 154,
                    "source": "YOUTUBE",
                    "externalId": "youtube-QO4y0G2M0m4",
                    "playUrl": "https://www.youtube.com/watch?v=QO4y0G2M0m4",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            }
            }
            }
        ]
    }
}


2. Boosting Query

我们可以通过布尔查询 must + must_not 先排除掉不想要的文档,再获取匹配的文档,但是有时候我们仅仅是想将匹配某些条件的分数降低,这时候,我们就可以使用 boosting query 去实现

查询逻辑

  • 在 positive 上填写你想要匹配的内容
  • 在 negative 上填写你不想要匹配的内容
  • 在 positive 查询的基础分数上,如果匹配中 negative 的内容,则将该文档分数乘以 negative_boost 值

Example

  • 查询歌手为 Luiz De Carvalho 的歌曲,但是又不太想匹配 Pobre Peregrino, Vol. 3专辑的歌曲
{
  "query": {
    "boosting": {
      "positive": {
        "term": {
          "artistNames.keyword": "Luiz De Carvalho"
        }
      },
      "negative": {
        "term": {
          "albumName.keyword": "Pobre Peregrino, Vol. 3"
        }
      },
      "negative_boost": 0.5
    }
  }
}
3. Constant Score Query

因为我们知道 filter context 是跟 score 无关的,但是有时候,我们又想让 filter context 可以有一个分数,加入 score 的计算,那么就可以考虑使用 contant score query ,即可以使用 filter, 有可以有一个分数值

查询逻辑

  • filter query 下查询是不计入 score 的,所以 constant score query 的能力就是赋予所有匹配文档一个固定的 score

Example
全文匹配歌手为 Luiz De Carvalho 的歌曲,固定分数是 10

{
  "query": {
    "constant_score": {
      "filter": {
        "match": { "artistNames": "Luiz De Carvalho" }
      },
      "boost": 10
    },
    "from": 0,
    "size": 2
  }
}

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 6,
        "successful": 6,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 450,
            "relation": "eq"
        },
        "max_score": 10,
        "hits": [
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25335347324886908",
                "_score": 10,
                "_source": {
                    "id": 25335347324886908,
                    "externalSongId": "spotify-4DnaSoC7rSXx5Ede2lcyDs",
                    "songName": "Em Teus Braços (Playback)",
                    "artistNames": [
                        "Luiz De Carvalho"
                    ],
                    "albumName": "Glória a Deus",
                    "albumId": 25335347327736112,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e02c1f27b64e40d66626140c95c",
                    "duration": 170,
                    "source": "YOUTUBE",
                    "externalId": "youtube-RLqBalnwL1E",
                    "playUrl": "https://www.youtube.com/watch?v=RLqBalnwL1E",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            },
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25335347323947197",
                "_score": 10,
                "_source": {
                    "id": 25335347323947197,
                    "externalSongId": "spotify-75rbWrFOi72F8tRRCZ5HvF",
                    "songName": "Graças a Deus (Playback)",
                    "artistNames": [
                        "Luiz De Carvalho"
                    ],
                    "albumName": "Meu Tributo",
                    "albumId": 25335347324927656,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e022b3617ef166aeb92f0e49684",
                    "duration": 227,
                    "source": "YOUTUBE",
                    "externalId": "youtube-UrlLN-mzv_8",
                    "playUrl": "https://www.youtube.com/watch?v=UrlLN-mzv_8",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            }
        ]
    }
}
  • score 都是 10 分
4. Dis Max Query

分离最大化查询 ,返回一或多子句查询匹配的文档,如果返回的文档与多个查询子句都匹配的情况下,则只将最佳匹配的子句的分数作为查询的评分返回,当然 dis_max query 还是可以通过 tie_breaker 参数处理最佳匹配子句与不同子句的权重

  • 分离最大化查询(Disjunction Max Query)指的是将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回 (可以通过 tie_breaker 调整权重)
  • tie_breaker 参数的作用就是调整最佳匹配子句分数的影响权重

tie_breaker

Tie_breaker 与 boost 修改权重的方式是有些不一样的

  • 0.0
    • 取分数最高字段的分数
  • 1.0
    • 取所有字段之和
  • 0.0 < n < 1.0
    • 取分数最高字段的分数 + (其他字段 * tie_breaker)

Example

curl -X GET "localhost:9200/test/_search?pretty"
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "java beginner" }},
                { "match": { "content":  "java beginner" }}
            ],
            "tie_breaker": 0.7
        }
    }
}

假设有 3 个文档

# 文档一
title: "i like java",                 # 0.4
content: "i am beginner"              # 0.4

# 文档二
title: "i like python",               # 0.0
content: "i am beginner",             # 0.4

# 文档三
title: "i like it",                   # 0.0
content: "i am java beginner"         # 0.7   

tie_breaker = 1 的情况下

  • 文档一: 0.4 + (1 * 0.4) = 0.8
  • 文档二: 0.4 + (1 * 0.0) = 0.4
  • 文档三: 0.7 + (1 * 0.0) = 0.7

tie_breaker = 0.5 的情况下

  • 文档一: 0.4 + (0.5 * 0.4) = 0.6
  • 文档二: 0.4 + (0.5 * 0.0) = 0.4
  • 文档三: 0.7 + (0.5 * 0.0) = 0.7
5. Function Score Query

在 Elasticsearch 中function_score是用于处理文档分值的 DSL,它会在查询结束后对每一个匹配的文档进行一系列的重打分操作,最后以生成的最终分数进行排序

GET /_search
{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "5", 
      "functions": [
        {
          "filter": { "match": { "test": "bar" } },
          "random_score": {}, 
          "weight": 23
        },
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 42
        }
      ],
      "max_boost": 42,
      "score_mode": "max",
      "boost_mode": "multiply",
      "min_score": 42
    }
  }
}

function score query 说白了一个加入分析功能的复杂查询,它提供了一些函数功能去改变匹配的分数

weight

  • 说白了就是权重,通过设置一个数字,文档的分数会乘以该数值,得到最终分数
  • 通常配合 filter 使用,因为过滤器只筛选出复合条件的文档,不计算分数,所以只要满足条件的文档分数都是 1,经过 weight 就可以更改为任意的数值

field_value_factor

  • 对文档的某个字段的值,经过加过处理了,得出一个分数

  • field 指定字段

    • 注意!必须是数字类型
  • factor 对字段值进行预处理,乘以指定的数值 (默认为 1),可以理解为字段分数的权重

  • modifier 将字段值进行加工,有很多种数学选项

    • none 不处理
    • log 对数
    • square 平方
    • sqrt 平方根

当我们搜索想要的视频时,我们希望点赞数高的可以排名更靠前的位置

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "一剪梅"
        }
      },
      "field_value_factor": {
        "field": "likes",
        "modifier": "sqrt",
        "factor": 0.1
      },
      "boost_mode": "sum"
    }
  }
}
  • score = score + sqrt(1 + 0.1 * likes)

random_score
使用 random_score 指定一个 seed 和 一个 field ,针对同一个 seed , 会返回固定的排序。可以实现不同的人请求,得到不同的排序结果,而同一个人请求可以得到相同的结果

{
  "query": {"function_score": {
    "query": {"match": {
      "title": "一剪梅"
    }},
    
    "random_score": {
        "seed": 1,
        "field": "uuid"
    },
    "boost_mode": "replace"
  }}
}

decay functions (衰减函数)

衰减函数提供了一个更牛逼的公式,对于一个字段,它有一个理想的值,而字段实际的值越皮哪里这个理想值 (无论上下),就越不符合期望。衰减函数适合应用在字段类型为数值,日期和地理位置等具备比较范围的情况

  • origin 原点: 该字段的理想型,匹配中,得满分 (boost: 1.0)
  • offset 偏移量: 与原点相差在偏移量之内的值也可以得到满分
  • scale 衰减规模: 当值超出了远点到偏移量这段范围,它得到的分数就开始衰减
  • decay 衰减值: 该字段可以被接受的值 (默认 0.5),相当于分界点,具体的效果与衰减的模式相关
  • DECAY_FUNCTION 衰减模式
    • linear 线性模式
    • exp 指数函数
    • gauss 高斯函数

比如我们要找房子, 只想找离公司 3 km 范围内的房子,超过这个范围的,兴趣就逐渐递减,直到离公司超过 10 km 就不再考虑了

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "公寓"
        }
      },
      "gauss": {
        "location": {
          "origin": { "lat": 40, "lon": 116 },
          "offset": "3km",
          "scale": "7km"
           }
         },
         "boost_mode": "sum"
    }
  }
}

最近的情况就是就在公司旁边,周围 3 km 范围是满意的,周围 10 km 是可接受的距离

script_score

当function_score 提供的多种默认处理分数的方式不能满足需求的时候,我们就可以通过脚本去实现自定义的分数规则

GET /_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "message": "elasticsearch" }
      },
      "script_score": {
        "script": {
          "source": "Math.log(2 + doc['my-int'].value)"
        }
      }
    }
  }
}

函数分数处理方式

score_mode
score_mode可以选择将各个函数得到的分数进行如何处理

  • multiply 分数相乘
  • sum 分数相加
  • avg 求平均
  • first 取第一个函数的分数
  • max 取最大的函数分数
  • Min 取最小的函数分数

boost_mode
score_mode 是决定各 function 函数得出的分数的处理方式,而 boost_mode 是 function 最终分数与 query 原始分的处理方式

  • multiply 相乘
  • replace 函数分替代原始查询分
  • sum 求和
  • avg 函数分和查询分的平均值
  • max 函数分与查询分取最大
  • min 函数分与查询分,取最小

function score query


全文检索 (full text queries)
1. Intervals query

间隔搜索

  • 为了更加灵活的控制查询时字符串在文本中匹配的距离和先后顺序,官方在 7.x 加入的间隔搜索特性,用户可单一或者组合多个规则集合在一个特定的 text field 上进行操作
curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "intervals" : {
      "my_text" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "my favorite food",
                "max_gaps" : 0,
                "ordered" : true
              }
            },
            {
              "any_of" : {
                "intervals" : [
                  { "match" : { "query" : "hot water" } },
                  { "match" : { "query" : "cold porridge" } }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

match rule

  • match

  • prefix

  • wildcard

  • fuzzy

  • all_of: 一组所有的规则必须都匹配的规则

  • any_of: 一组只要其中一个规则匹配即可的规则

match

  • query
  • max_gaps
  • ordered

all_of

  • Intervals : 所有必须要匹配一组规则
  • max_gaps: 匹配词之间的最大位置间隔数
    • 默认 -1 , 代表无间隔要求
    • 0 代表必须相邻
  • ordered: intervals 之间是有序的
    • 默认为 false
  • filter: 过滤规则

any_of

  • Intervals: 匹配一个规则
  • filter: 过滤规则

filter

此 filter 不同于 之前在 match query 提到的 filter ,它有自己独特的语法

  • after: query intervals 在 filter intervals 之后
  • before:query intervals 在 filter intervals 之前
  • containing: query intervals 包含 filter intervals 则为 true
    • bool query (must + must)
  • not_containing: query intervals 不包含 filter intervals 则为 true
    • bool query (must + must not)

Example

  • 歌曲名(查找 Teu xxx Chamar 或 Teu xxx Playback)
    • 查询 Teu 在 Chamar 之前的歌曲
    • 查找 Teu 在 Playback 之前的歌曲
{
  "query": {
    "intervals" : {
      "songName" : {
        "all_of" : {
          "ordered" : true, # intervals 之间有顺序
          "max_gaps": 0, # 且必须相邻
          "intervals" : [
            {
              "match" : {
                "query" : "Teu O",
                "max_gaps" : 0, # Teu 和 O 必须相邻
                "ordered" : false # Teu 和 O 不需要顺序
              }
            },
            {
              "any_of" : {
                "intervals" : [
                  { "match" : { "query" : "Chamar" } },
                  { "match" : { "query" : "Playback" } }
                ]
              }
            }
          ]
        }
      }
    }
  }
}
  • 歌名中 Playback 在 Teu 之后的
{
  "query": {
    "intervals" : {
      "songName" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "Playback",
                "max_gaps" : 0,
                "ordered" : true
              }
            }
          ],
          "filter": {
        	"after": {
        		"match": {
        			"query": "Teu"
        		}
        	}
        }
        }
      }
    }
  }
}
  • 过滤掉包含 Chamar 的(即符合不包含 Chamar 就符合条件)
{
  "query": {
    "intervals" : {
      "songName" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "Teu",
                "max_gaps" : 0,
                "ordered" : true
              }
            },
            {
              "any_of" : {
                "intervals" : [
                	{ "match" : { "query" : "Chamar" } },
                	{ "match" : { "query" : "Playback" } }
                ]
              }
            }
          ],
          "filter": {
        	"not_containing": {
        		"match": {
        			"query": "Chamar"
        		}
        	}
        }
        }
      }
    }
  }
}
2. match
  • query: 查询文本

  • analyzer: 分词器

  • fuzziness: 最大编辑距离(莱文斯坦距离),用于模糊匹配,默认为 0,即不可编辑

    • 0,1,2 表示可允许的最大莱文斯坦距离
    • AUTO 自动根据词项的长度产生可编辑的距离
  • fuzzy_transpositions: 是否允许模糊换位,默认 true, 可搭配 fuzziness 使用

  • max_expansions: 最大短语扩展数 ,默认 50

  • prefix_length: 前多少个字符不开启模糊匹配

  • lenient: 宽容情况,当某个字段是数值类型,而参数传了字符串类型时,默认为 false ,会报错, 为 true 时,不会报错,会转换查询

  • operator: 当 query = “周杰伦”

    • OR 或: 文档只要匹配 “周” 或 “杰” 或 “伦” 就可以匹配中
    • AND 且 文档必须 “周” , “杰” , “伦” 都匹配中
  • minimum_should_match:文档需要匹配中多少百分比的分词才允许返回

    • 比如周杰伦,我们要求匹配分词超过 百分之 60 才返回,那么只含有周的文档是不会返回的,至少匹配中 “周,杰” 或 ”伦,杰“ 等
    • 可以降低搜索结果,减少长尾,擦边的文档
{
	"query": {
		"match": {
			"songName": {
				"query" : "O Teu Chamer",
				"fuzziness": 0,
				"max_expansions": 1,
				"prefix_length": 3,
				"operator": "OR"
			}
		}
	}
}
3. match_bool_prefix query

match_bool_prefix

  • match_bool_prefix 查询将输入文本通过指定的 analyzer 分词器处理为多个 term, 然后基于前些 term 进行 term query, 但最后一个 term 使用前缀查询
  • term 查询支持 match 的多种参数, prefix 不支持模糊匹配的参数
    • operator
    • fuzziness
    • Prefix_length
    • max_expansions

Example

{
	"query": {
		"match_bool_prefix": {
			"songName": "O Teu Ch"
		}
	}
}
{
	"query": {
		"match_bool_prefix": {
			"songName": "Teu O Ch"
		}
	}
}
  • 上面两者都可以得到期望结果,分词为O, Teu, Ch, 无序 (operator = OR), 前两者使用 term query, 最后的Ch 则使用 prefix query, 类似于下面的 bool query
4. match_phrase query

短语查询

  • match_phrase 的基本单位是词组,词组无法模糊匹配
  • 分词成的多个 term 必须精确,并且按顺序排序。在顺序正确的情况下,允许 term 之间有词组间隔,由 slop 控制,默认为 0,即两两词组必须相连 (有点像之间说过的 interval query , 也可以实现类似功能)
  • 说白了,跟 match 的区别时,term 是确切的,term 之间是有序的

Example

查询 O Chamar 词组

# 无结果
{
	"query": {
		"match_phrase":  {
			"songName": {
				"query": "O Chamar",
				"slop": 0
			}
		}
	}
}
# 有结果
{
	"query": {
		"match_phrase":  {
			"songName": {
				"query": "O Chamar",
				"slop": 1
			}
		}
	}
}

无法搭配 fuzziness , 即 match_phrase 没有模糊匹配模式

同样是要查询 O Teu Chamer, 看与 match 之间的区别

{
	"query": {
		"match":  {
			"songName": "O Chemar Teu" # 乱序,且 Chemar 拼写错误
		}
	}
}
# 可以查询到期望结果
{
	"query": {
		"match_phrase":  {
			"songName": "O Chemar Teu"
		}
	}
}
# 凉凉

{
	"query": {
		"match_phrase":  {
			"songName": "O Chamar Teu" # 乱序,但修正单词错误
		}
	}
}
# 凉凉

{
	"query": {
		"match_phrase":  {
			"songName": "O Teu Chamar"
		}
	}
}
# 有结果
5. match_phrase_prefix query

短语前缀查询

  • 前几个 term 使用 match_phrase 查询,最后一个 term 则采用 prefix 查询
  • match_bool_prefix 和 match_phrase_prefix 区别也很简单,说白了就是 match 和 match_phrase 的区别
  • match_phrase_prefix 通常可以用于给用户输入提供建议提醒
  • 常用参数
    • max_expansion : 最大扩展数
    • slop: 分词词组之间最多间隔多少个位置,默认是 0,即必须相邻

Example

查询O Teu Ch开头的歌曲

{
	"query": {
		"match_phrase_prefix": {
			"songName": {
				"query": "O Teu Ch",
				"slop": 0,
				"max_expansions": 50
			}
		}
	}
}

找到两首 O Teu Chamar ,O Teu Chamar - Playback

{
    "took": 5,
    "timed_out": false,
    "_shards": {
        "total": 6,
        "successful": 6,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 351.71133,
        "hits": [
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25329053628305609",
                "_score": 351.71133,
                "_source": {
                    "id": 25329053628305609,
                    "externalSongId": "spotify-6xyCay9wgDMf5phcovxBKO",
                    "songName": "O Teu Chamar",
                    "artistNames": [
                        "Jotta A"
                    ],
                    "albumName": "Essência",
                    "albumId": 25329053630400886,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e0294d215ec962e4c98fceb5e26",
                    "duration": 240,
                    "source": "YOUTUBE",
                    "externalId": "youtube-LP6TebWWPwE",
                    "playUrl": "https://www.youtube.com/watch?v=LP6TebWWPwE",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            },
            {
                "_index": "song",
                "_type": "_doc",
                "_id": "25329053631010314",
                "_score": 297.21338,
                "_source": {
                    "id": 25329053631010314,
                    "externalSongId": "spotify-3DJn4rY1g4llBrm1HWXABA",
                    "songName": "O Teu Chamar - Playback",
                    "artistNames": [
                        "Jotta A"
                    ],
                    "albumName": "Essência (Playback)",
                    "albumId": 25329053632022016,
                    "genres": [],
                    "coverUrl": "https://i.scdn.co/image/ab67616d00001e02beb06d1a13ab2cf025c226b1",
                    "duration": 242,
                    "source": "YOUTUBE",
                    "externalId": "youtube-nXHgXVIF-bE",
                    "playUrl": "https://www.youtube.com/watch?v=nXHgXVIF-bE",
                    "lyricIds": [],
                    "areas": [
                        "BR_LP"
                    ],
                    "status": "ONLINE",
                    "dead": false
                }
            }
        ]
    }
}
6. multi_match query

多字段查询

  • 类似于 match query 的多字段版本,但是更强大
  • 不管是 match, match_bool_prefix, match_phrase, match_phrase_prefix 都是针对一个字段的全文检索,而 multi_match 针对多个字段进行同一个查询
  • 虽然复合查询也可以实现同样的效果,但由单个查询实现会更简洁

type

  • best_fields 默认类型

    • match query 多字段版本
    • 就像 dis_max 的最佳匹配
  • most_fields

    • match query 多字段版本
    • 适用于同一个字段的多种分析器, 让多个 fields 参与到总分计算做,权重比较均匀
  • pharse

    • match_phrase 的多字段版本
  • phrase_prefix

    • match_phrase_prefix 的多字段版本

Example

  • *模糊匹配名称,^2 相当于给该字段修改权重 ,等价于 boost = 2.0
{
	"query": {
    	"multi_match": {
        	"query":  "Ao",
        	"fields": [ "*Name", "artistNames^2" ] 
     	}
    }
}

(Best_fields) 查询 songName, artistNames, albumName 之中含有 Teu 的歌曲

{
  "query": {
    "multi_match" : {
      "query":    "Ao", 
      "fields": [ "songName", "albumName","artistNames" ],
      "type": "best_fields",
      "tie_breaker":          0.3
    }
  }
}

它实际上就是 dis_max 符合查询的简洁版本

{
  "query": {
    "dis_max": {
      "queries": [
        { "match": { "songName": "Ao" }},
        { "match": { "albumName": "Ao" }},
        { "match": { "artistNames": "Ao" }}
      ],
      "tie_breaker": 0.3
    }
  }
}

(most_feilds) 针对 title 的多种分词进行搜索

{
  "query": {
    "multi_match" : {
      "query":      "quick brown fox",
      "type":       "most_fields",
      "fields":     [ "title", "title.original", "title.shingles" ]
    }
  }
}

参考


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Elasticsearch 查询语句可以使用 Query DSL 进行构建。以下是一些常见的查询语句示例: 1. 匹配查询:用于匹配一个特定字段中的值。 ``` GET /_search { "query": { "match": { "title": "elasticsearch" } } } ``` 2. 短语查询:用于匹配一个特定字段中的短语。 ``` GET /_search { "query": { "match_phrase": { "title": "elasticsearch tutorial" } } } ``` 3. 范围查询:用于匹配一个特定字段中的数值范围。 ``` GET /_search { "query": { "range": { "age": { "gte": 18, "lte": 30 } } } } ``` 4. 布尔查询:用于组合多个查询条件。 ``` GET /_search { "query": { "bool": { "must": [ { "match": { "title": "elasticsearch" } }, { "match": { "description": "tutorial" } } ] } } } ``` 5. 聚合查询:用于对结果进行聚合计算。 ``` GET /_search { "aggs": { "avg_age": { "avg": { "field": "age" } } } } ``` 以上仅是一些常见的查询语句示例,Elasticsearch 还支持许多其他类型的查询。请参阅官方文档以了解更多信息。 ### 回答2: Elasticsearch 是一个开源的分布式搜索和分析引擎,它提供了强大的查询功能来检索和分析大量的数据。 Elasticsearch 查询语句可以使用 JSON 格式来构建,主要分为两种类型:查询查询语句和过滤查询语句。 查询查询语句用于根据特定的条件从索引中检索文档。常见的查询类型包括匹配查询、多字段查询、范围查询和布尔查询等。匹配查询用于在指定字段中搜索指定的词语,多字段查询可以在多个字段中搜索相同的词语,范围查询支持按照范围来搜索结果,而布尔查询则可以通过逻辑运算符组合多个查询条件。 过滤查询语句用于根据特定的条件过滤文档。与查询查询语句不同的是,过滤查询不会计算相关度分数,只关心是否匹配。常见的过滤查询类型有 term 过滤、范围过滤和 bool 过滤等。term 过滤用于精确匹配一个词语,范围过滤用于按照指定范围过滤结果,bool 过滤则可以通过逻辑运算符组合多个过滤条件。 除了查询和过滤,Elasticsearch 还支持一些聚合函数(aggregations),用于对搜索结果进行统计和分析。聚合查询可以对结果集进行分组、排序、计算总和、平均值等操作,从而提供更丰富的数据分析功能。 总之,Elasticsearch 查询语句是非常灵活和强大的,可以根据不同的需求组合不同的查询和过滤条件,实现高效的数据检索和分析。 ### 回答3: Elasticsearch是一个开源的分布式搜索和分析引擎,提供了强大的查询功能。查询语句是用户用来向Elasticsearch发送请求并获取结果的指令。 Elasticsearch查询语句可以分为两种,一种是基于URI的查询语句,另一种是基于请求体的查询语句。 基于URI的查询语句通常用于简单的查询请求,语法类似于URL。例如,要查询名为"products"的索引下的所有文档,可以使用以下查询语句: GET /products/_search 基于请求体的查询语句更为灵活,可以实现更复杂的查询功能。请求体是一个JSON对象,包含了查询的参数和条件。以下是一个常见的基于请求体的查询语句示例: POST /products/_search { "query": { "match": { "name": "手机" } } } 上述查询语句使用了"match"查询,指定了要查询的字段为"name",查询的关键词为"手机"。这将返回所有名为"手机"的文档。 此外,Elasticsearch还提供了许多其他类型的查询语句,包括布尔查询、范围查询、模糊查询等。用户可以根据需要选择合适的查询语句以实现精确的搜索结果。 总之,Elasticsearch查询语句是通过URI或请求体来发送查询请求的指令,使用不同类型的查询语句可以实现不同的搜索功能。用户可以根据自己的需求选择合适的查询语句,并通过分析返回的结果来满足他们的搜索和分析需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值