ES 深入理解搜索

2020-02-04  本文已影响0人  鸿雁长飞光不度

1.基于Term的查询

Term是表达语义的最小单位,搜索和自然语言处理都用Term处理。

案例

POST /products/_bulk
{"index":{"_id":1}}
{"product_id":"ABC-DEF","desc":"iPhone"}
{"index":{"_id":2}}
{"product_id":"ABC-bba","desc":"iPad"}

POST /products/_search
{
  "query": {
    "term": {
      "desc": {
        "value": "iPhone"//查不到,"iphone"可以,
      }
    }
  }
}
POST /products/_search
{
  "query": {
    "term": {
      "product_id.keyword": {
        "value": "ABC-bba"
      }
    }
  }
}
忽略计算评分
 {
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "product_id.keyword": "ABC-bba"
        }
      }
    }
  }
}

2.基于全文的查询

可以通过match、match phrase、query string这些类的查询实现。

特点:

详细内容见:https://www.jianshu.com/p/8e70f80cca80

3.结构化搜索

3.1 结构化数据

3.2 ES的结构化搜索

范围查询案例:

POST products/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "range": {
          "price": {
            "gte": 10,
            "lte": 20
          }
        }
      },
      "boost": 1.2
    }
  }
}

4.相关性算分

搜索的相关性算法,描述了一个文档和查询语句的匹配程度,ES会对每个匹配的查询条件做score,ES5以前用TF-IDF算法,现在用BM25/

一些基本概念:

词频(IF):检索词在一片文档中出现的频率。检索词出现的次数/文档总字数。可以把各个词频(除去没有用的词)想加得到一个评分。

逆文档频率(IDF):log(全部文档数/检索词出现过的文档总数)

TF-IDF:本质就是将TF加权求和,TF(区块链)IDF(区块链)+TF(的)IDF(的)+TF(应用)*IDF(应用)

4.1通过Boosting控制相关度

POST score_test/_search
{
  "query": {
    "boosting": {
      "positive": {
        "term": {
          "content": "live"
        }
      },
      "negative":{
        "term":{
          "content":"he"
        }
      },
      "negative_boost":0.3
    }
  }
}

匹配带live的,如果content字段里面包含了he,减分0.3

5. Query & Filter 多字段查询

5.1 bool查询

应用于多个字段,多个条件的符合查询。

字段值 说明
must 必须匹配,贡献算分
should 选择性匹配,贡献算分
must_not filter context查询子句,必须不能匹配,不算评分
filter filter context 必须匹配,但是不贡献算分。

案例

GET movies/_search
{
  "size": 20, 
  "query": {
    "bool": {
      "must": [
        {"term": {
          "title": {
            "value": "bob"
          }
        }}
      ], 
      "filter": [
        {
          "range": {
            "year": {
              "gte": 1991,
              "lte": 1994
            }
          }
        }
      ],
      "should": [
        {"term": {
          "id": {
            "value": "3809"
          }
        }},
         {"term": {
          "id": {
            "value": "1994"
          }
        }}
      ],
       "minimum_should_match": 1
    }
  }
}

标题里面包含bob,发行时间在1991年到1994年,最好id是3809或者1994,should条件最少满足一个。

嵌套案例,boost会增加。

GET movies/_search
{
 "query": {
   "bool": {
     "should": [
       {"bool": {
         "must": [
           {"term": {
             "title": {
               "value": "bob",
               "boost": 1.1
             }
           }}
         ]
       }}
     ]
   }
 }
}

5.2 单字符串多字段查询

案例,查询title或者year出现2012的电影,should换成must表示且。

GET movies/_search
{
  "explain": true,
  "query": {
    "bool": {
      "should": [
        {"match": {"title": "2012" }},
        {"match": {"year": "2012"}}
      ]
    }
  }
}

评分规则:

基于这个评分规则,可能评分可能不是自己想要的。可以使用Disjunction Max Query,这样就会选择分数最佳的查询的结果的值,返回,不再是相加。

5.3 Disjunction Max Query

GET search_test/_search
{
  "query": {
    "dis_max": {
      "should": [
        {"match": {"title": "php class" }},
        {"match": {"body": "php class"}}
      ],
      "tie_breaker": 0.7
    }
  }
}

找出最大值,然后把其他的评分乘以0.7,然后想加得到一个新的评分。

5.3 Mulit Match

5.3.1 最佳字段(best field)

当字段之间存在相互竞争,又相互关联。类似title和body,评分来自最匹配的字段。

案例

POST movies/_search
{
  "query": {
    "multi_match": {
      "type": "best_fields", 
      "query": "1993",
      "fields": [
        "title",
        "id"
      ],
      "minimum_should_match": 1
      , "tie_breaker": 0.2
    }
  }
}
5.3.2 多字段(most field)

案例

PUT /titles 
{
  "mappings": {
    "properties": {
      "title":{
        "type": "text",
        "analyzer": "english",
        "fields": {
          "std":{
            "type":"text",
            "analyzer":"standard"
          }
        }
      }
    }
  }
}

std字段不会进行分词,是对title的优化
查询

GET /titles/_search
{
  "query": {
    "multi_match": {
      "type": "most_fields", 
      "query": "1",
      "fields": ["title^10","title.std"]
    }
  }
}

mostfield方式,title设置权重百分10。

5.3.3 混合字段(cross field)

对于某些实体,人名、地址。需要在多个字段中确定信息,单个字段只能作为整体的一部分。希望在列出的字段中尽可能找到多的词。

案例

POST address/_search
{
"query": {
"multi_match": {
"query": "poland street w",
"fields": ["street","city","country","postcode"],
"type": "cross_fields",
"operator": "and"
}
}
}

相对于通过_copyto方式,减少了磁盘空间,同时可以在搜索的时候为单个字段提升权重

6 search template

将搜索定义成模板,定义和使用的案例如下

POST _scripts/tmdb
{
"script":{
"lang":"mustache",
"source":{
"_source":["title","overview"],
"size":20,
"query":{
"multi_match":{
"query":"{{q}}",
"field":["title","overview"]
}
}
}
}
}
POST tmdb/_search/template
{
"id":"tmdb",
"params": {
"q":"basketball with"
}
}

7 index alias

给索引创建一个别名,实现灵停机运维。通过别名,索引的改名和重建程序不用动。

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "movies",
        "alias": "moveis-2019",
        "filter": {
          "range": {
            "year": {
              "gte": 2012
            }
          }
        }
      }
    }
  ]
}
上一篇下一篇

猜你喜欢

热点阅读