ElasticSearch查询(match和term)
2018-12-19 本文已影响0人
隔壁公司的程序员
term
PUT news
{
"mappings": {
"properties": {
"tags": {
"type": "text",
"analyzer": "whitespace"
}
}
}
}
POST /news/_doc/1
{"tags":"Hello World"}
# 有值
GET /news/_search
{"query":{"term":{"tags":"Hello"}}}
# 无值
GET /news/_search
{"query":{"term":{"tags":"Hello World"}}}
term代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词,所以我们的搜索词必须是文档分词集合中的一个
- 假设建立索引时,此字段 "无分词",则完全匹配此字段(如果对于某个字段,你想精确匹配,即搜索什么词匹配什么词,类似sql中的=操作,则应该采取此操作)
- 假设建立索引时,此字段进行分词(假定分词后的结果为Hello、World),则只要term搜索Hello或者World,均可匹配此条数据,但是 "Hello World" 并不在分词集合中,即其无法匹配该文档
match
# 有值
GET /news/_search
{"query":{"match":{"tags":"Hello World"}}}
# 无值
GET /news/_search
{"query":{"match":{"tags":"llo W"}}}
- match查询会先对搜索词进行分词,分词完毕后再逐个对分词结果进行匹配,相对于term的精确搜索,match是分词匹配搜索,match搜索还有两个相似功能的变种:match_phrase、multi_match
- 例如,当我们搜索 "Hello World",搜索词会先分词为"Hello" 和 "World" ,只要文档中包含其任意一个,都会被匹配,即可以匹配到上述的Hello World的那个Document(假如分词了的话)
- 对于match搜索,可以按照分词后的分词集合的or或者and进行匹配,默认为or,这也是为什么默认只要有一个分词出现在文档中就会被搜索出来,同样的,如果我们希望是所有分词都要出现,那只要把匹配模式改成and就行了
{
"query": {
"match": {
"tags": {
"query": "Hello World",
"operator": "and"
}
}
}
}
match_phrase
- match_phrase为按短语搜索,这个可能先用英文来解释会直观一点(中文分词后其实已经是一个一个有具体意思的词语)。英文中以空格分词,因此分词后是一个个的单词,当想搜索类似hope so这样的短语时,你或许并不想将一些只含有hope的文档搜索出来,也不想将一些类似I hope ×××. So ××这样的搜索出来,此时,就可以用match_phrase。
- match_phrase的搜索方式和match类似,先对搜索词建立索引,并要求所有分词必须在文档中出现(像不像operator为and的match查询),除此之外,还必须满足分词在文档中出现的顺序和搜索词中一致且各搜索词之间必须紧邻,因此match_phrase也可以叫做紧邻搜索。
- 紧邻对于匹配度要求较高,为了减小精度增加可操作性,引入了slop参数。该参数可以指定相隔多少个词仍被算作匹配成功。
- 需要注意的是,当slop的值过大时(超出文档总分词数),那么分词数据将可以是随意的,即跟operator为and的match查询效果一样。
multi_match
- https://www.elastic.co/guide/cn/elasticsearch/guide/current/multi-match-query.html
- https://www.elastic.co/guide/cn/elasticsearch/guide/current/_best_fields.html
- https://www.elastic.co/guide/cn/elasticsearch/guide/current/_tuning_best_fields_queries.html
- best_fields
- 默认情况下,该查询以best_fields类型执行,它会为每个字段生成一个match查询,然后将这些查询包含在一个dis_max查询(dis_max查询就是返回最高分数的那个文档)中。下面的dis_max查询:
{
"dis_max": {
"queries": [
{
"match": {
"FIELD1": {
"query": "Hello World",
"minimum_should_match": "30%"
}
}
},
{
"match": {
"FIELD2": {
"query": "Hello World",
"minimum_should_match": "30%"
}
}
},
],
"tie_breaker": 0.3
}
}
可以通过multi_match简单地重写如下:
{
"multi_match": {
"query": "Hello World",
"type": "best_fields",
"fields": [ "FIELD1", "FIELD2" ],
"tie_breaker": 0.3,
"minimum_should_match": "30%"
}
}
- 字段名可以通过通配符指定:任何匹配了通配符的字段都会被包含在搜索中
你可以通过下面的查询来匹配 A_title,B_title 以及 C_title字段
{
"multi_match": {
"query": "Hello World",
"fields": "*_title"
}
}
- 个别字段可以通过caret语法进行提升:仅需要在字段名后添加^boost,其中的boost是一个浮点数:
{
"multi_match": {
"query": "Quick brown fox",
"fields": [ "*_title", "A_title^10" ]
}
}
A_title字段的boost值为10,而 B_title 和 C_title 字段的boost值为默认的1。
- most_fields
- most_field就是匹配词干的字段数越多,分数越高,也可设置权重boost
- cross-fields
- 指的是一个唯一标识,跨域了多个字段,比如人的标识是名字,一个建筑的标识是地址,姓名跨域散落在多个field中,比如first_name和last_name,一个地址也可以散落在多个字段中,比如country,province,city中。使用multi_match,指定类型为cross_fields进行匹配操作(也可以选择新增字段等其他方式进行操作!!)