美文网首页
二十、Elastics Search使用term filter来

二十、Elastics Search使用term filter来

作者: 书写只为分享 | 来源:发表于2019-11-27 00:54 被阅读0次

    1、term filters搜索

    (1)插入一些测试帖子数据

    POST /forum/article/_bulk
    { "index": { "_id": 1 }}
    { "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" }
    { "index": { "_id": 2 }}
    { "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" }
    { "index": { "_id": 3 }}
    { "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" }
    { "index": { "_id": 4 }}
    { "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }
    

    查看Mapping
    GET /forum/_mapping/article

    {
      "forum": {
        "mappings": {
          "article": {
            "properties": {
              "articleID": {
                "type": "keyword"
              },
              "hidden": {
                "type": "boolean"
              },
              "postDate": {
                "type": "date"
              },
              "userID": {
                "type": "long"
              }
            }
          }
        }
      }
    }
    

    现在es 5.2版本,type=text,默认会设置两个field,一个是field本身,比如articleID,就是分词的;还有一个的话,就是field.keyword,articleID.keyword,默认不分词,会最多保留256个字符

    (2)根据用户ID搜索帖子

    GET /forum/article/_search
    {
    "query" : {
    "constant_score" : {
    "filter" : {
    "term" : {
    "userID" : 1
    }
    }
    }
    }
    }
    term filter/query:对搜索文本不分词,直接拿去倒排索引中匹配,你输入的是什么,就去匹配什么

    (3)根据帖子ID搜索帖子

    GET /forum/article/_search
    {
    "query" : {
    "constant_score" : {
    "filter" : {
    "term" : {
    "articleID" : "XHDK-A-1293-#fJ3"
    }
    }
    }
    }
    }
    查不到数据,因为默认是analyzed的text类型的field,建立倒排索引的时候,就会对所有的articleID分词,分词以后,原本的articleID就没有了,只有分词后的各个word存在于倒排索引中。
    (4)重建索引或者使用内至的keyword

    DELETE /forum

    PUT /forum
    {
    "mappings": {
    "article": {
    "properties": {
    "articleID": {
    "type": "keyword"
    }
    }
    }
    }
    }

    GET /forum/article/_search
    {
    "query" : {
    "constant_score" : {
    "filter" : {
    "term" : {
    "articleID.keyword" : "XHDK-A-1293-#fJ3"
    }
    }
    }
    }
    }
    (5)梳理学到的知识点
    (1)term filter:根据exact value进行搜索,数字、boolean、date天然支持
    (2)text需要建索引时指定为not_analyzed,才能用term query
    2、filter执行原理深度剖析(bitset机制与caching机制)

    (1)在倒排索引中查找搜索串,获取document list

    date来举例

    word doc1 doc2 doc3

    2017-01-01 * *
    2017-02-02 * *
    2017-03-03 * * *

    filter:2017-02-02

    到倒排索引中一找,发现2017-02-02对应的document list是doc2,doc3

    (2)为每个在倒排索引中搜索到的结果,构建一个bitset,[0, 0, 0, 1, 0, 1]

    非常重要

    使用找到的doc list,构建一个bitset,就是一个二进制的数组,数组每个元素都是0或1,用来标识一个doc对一个filter条件是否匹配,如果匹配就是1,不匹配就是0

    [0, 1, 1]

    doc1:不匹配这个filter的
    doc2和do3:是匹配这个filter的

    (3)遍历每个过滤条件对应的bitset,优先从最稀疏的开始搜索,查找满足所有条件的document

    后面会讲解,一次性其实可以在一个search请求中,发出多个filter条件,每个filter条件都会对应一个bitset,遍历每个filter条件对应的bitset,先从最稀疏的开始遍历,就可以先过滤掉尽可能多的数据

    [0, 0, 0, 1, 0, 0]:比较稀疏
    [0, 1, 0, 1, 0, 1]
    请求:filter,postDate=2017-01-01,userID=1
    postDate: [0, 0, 1, 1, 0, 0]
    userID: [0, 1, 0, 1, 0, 1]

    遍历完两个bitset之后,找到的匹配所有条件的doc,比如就是doc4

    就可以将document作为结果返回给client了

    (4)caching bitset,跟踪query,在最近256个query中超过一定次数的过滤条件,缓存其bitset。对于小segment(<1000,或<3%),不缓存bitset。

    segment数据量很小,此时哪怕是扫描也很快;segment会在后台自动合并,小segment很快就会跟其他小segment合并成大segment,此时就缓存也没有什么意义,segment很快就消失了

    比如postDate=2017-01-01,[0, 0, 1, 1, 0, 0],可以缓存在内存中,这样下次如果再有这个条件过来的时候,就不用重新扫描倒排索引,反复生成bitset,可以大幅度提升性能。

    在最近的256个filter中,有某个filter超过了一定的次数,次数不固定,就会自动缓存这个filter对应的bitset

    filter比query的好处就在于会caching,但是之前不知道caching的是什么东西,实际上并不是一个filter返回的完整的doc list数据结果。而是filter bitset缓存起来。下次不用扫描倒排索引了。

    (5)filter大部分情况下来说,在query之前执行,先尽量过滤掉尽可能多的数据

    query:是会计算doc对搜索条件的relevance score,还会根据这个score去排序
    filter:只是简单过滤出想要的数据,不计算relevance score,也不排序

    (6)如果document有新增或修改,那么cached bitset会被自动更新

    (7)以后只要是有相同的filter条件的,会直接来使用这个过滤条件对应的cached bitset

    3、基于bool组合多个filter条件来搜索数据
    (1)搜索发帖日期为2017-01-01,或者帖子ID为XHDK-A-1293-#fJ3的帖子,同时要求帖子的发帖日期绝对不为2017-01-02
    GET /forum/article/_search

    GET /forum/article/_search
    {
      "query": {
        "constant_score": {
          "filter": {
            "bool": {
              "should":[
                {"term":{"postDate":"2017-01-01"}},
                {"term":{"articleID":"XHDK-A-1293-#fJ3"}}
                ],
                "must_not":{
                  "term":{
                    "postDate":"2017-01-02"
                  }
                }
            }
          }
        }
      }
    }
    

    must,should,must_not,必须匹配,可以匹配其中任意一个即可,必须不匹配
    (2)搜索帖子ID为XHDK-A-1293-#fJ3,或者是帖子ID为JODL-X-1937-#pV7而且发帖日期为2017-01-01的帖子
    GET /forum/article/_search

    GET /forum/article/_search
    {
      "query": {
        "constant_score": {
          "filter": {
            "bool": {
              "should":[
                {"term":{
                  "articleID":"XHDK-A-1293-#fJ3"
                }},
                {
                  "bool":{
                    "must":[
                      {"term":{
                        "articleID":"JODL-X-1937-#pV7"
                      }},{
                        "term":{
                          "postDate":"2017-01-01"
                        }
                      }
                      ]
                  }
                }
                
                
                ]
            }
          }
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:二十、Elastics Search使用term filter来

          本文链接:https://www.haomeiwen.com/subject/wfeuwctx.html