ES 查询优化(二)

2018-05-23 17:18:39 浏览数 (1)

接上一篇继续介绍。

1、查询精确匹配

假设有 { "tags" : ["search"] } { "tags" : ["search", "open_source"] } 两个文档,{ "term" : { "tags" : "search" } }都能匹配,但想只搜索包含一个的值,怎么办? 插入数据时多加一个长度字段: { "tags" : ["search"], "tag_count" : 1 } { "tags" : ["search", "open_source"], "tag_count" : 2 } 查找时加上tag_count精确查找即可。

代码语言:javascript复制
GET /_search
{
    "query": {
        "constant_score": {
            "filter": {
                "term": {
                    "tag_count": 1
                }
            }
        },
        "term": {
            "tags": "search"
        }
    }
}
2、 忽略多个近义词匹配的相关性

我们知道jump, leap, 和 hop是近义词,它们表示的是同样的概念,因此在匹配时,我们希望匹配jump和leap的文档的相关性不能比仅匹配jump的文档高,该怎么做呢?设置coordination factor (coord)即可。

代码语言:javascript复制
GET /_search
{
  "query": {
    "bool": {
      "disable_coord": true,
      "should": [
        { "term": { "text": "jump" }},
        { "term": { "text": "hop"  }},
        { "term": { "text": "leap" }}
      ]
    }
  }
}
3、查询时提高索引的相关性

比如说,我们es存储的是nginx的日志,昨天nginx出问题了,那么查看最近七天的日志时,为了快速找出昨天的错误,也不忽略前天的错误,那么昨天的nginx-log包含error的文档相关性应该比前天的高。默认的boost为1。

代码语言:javascript复制
GET /docs_2017_12_*/_search 
{
  "indices_boost": { 
    "docs_2017_12_10": 3,
    "docs_2017_12_09": 2
  },
  "query": {
    "term": {
      "text": "error"
    }
  }
}
4、更改score计算方法

ES5.0之前默认用的是tf-idf来计算相关性,5.0之后(lucene6)用的BM25来计算相关性。所以这个就不说了。

5、针对数组字符串,match_phrase匹配不准确
代码语言:javascript复制
PUT /my_index/groups/1
{
    "names": [ "John Abraham", "Lincoln Smith"]
}

GET /my_index/groups/_search
{
    "query": {
        "match_phrase": {
            "names": "Abraham Lincoln"
        }
    }
}

上述查询可以匹配的到插入的文档。原因是针对names建倒排时,各位置如下:

代码语言:javascript复制
Position 1: john
Position 2: abraham
Position 3: lincoln
Position 4: smith

所以查询“Abraham Lincoln”可以查询的到。针对于这种情况通过设置position_increment_gap解决。

代码语言:javascript复制
DELETE /my_index/groups/ 

PUT /my_index/_mapping/groups 
{
    "properties": {
        "names": {
            "type":                "string",
            "position_increment_gap": 100
        }
    }
}

重新导入数据,建索引时各个位置就会如下所示:

代码语言:javascript复制
Position 1: john
Position 2: abraham
Position 103: lincoln
Position 104: smith

这样再次用match_phrase查询时,由于position没有互相挨着,就查询不到“Abraham Lincoln”。

6、Post Filter用于过滤返回的结果集
代码语言:javascript复制
PUT /shirts
{
    "mappings": {
        "item": {
            "properties": {
                "brand": { "type": "keyword"},
                "color": { "type": "keyword"},
                "model": { "type": "keyword"}
            }
        }
    }
}

假设我们现在需要找出brand为gucci的所有颜色种类,但是只显示按model聚合的红色的文档,查询语句如下:

代码语言:javascript复制
GET /shirts/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": { "brand": "gucci" } 
      }
    }
  },
  "aggs": {
    "colors": {
      "terms": { "field": "color" } 
    },
    "color_red": {
      "filter": {
        "term": { "color": "red" } 
      },
      "aggs": {
        "models": {
          "terms": { "field": "model" } 
        }
      }
    }
  },
  "post_filter": { 
    "term": { "color": "red" }
  }
}
es2

0 人点赞