第十四篇 elasticsearch的结构化搜索(全)

1. 使用term、filter来搜索数据

1.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" }

es是支持json document格式的,扩展性和灵活性非常之好,随着业务的增加可以很方便的随时添加field。

1.2 根据用户ID搜索帖子

GET /forum/article/_search
{
    "query" : {
        "constant_score" : { 
            "filter" : {
                "term" : { 
                    "userID" : 1
                }
            }
        }
    }
}

query filter term搜索对文本不分词,直接拿去倒排索引匹配,你输入的是什么就去匹配什么

1.3 使用_mapping查看数据类型

GET /forum/_mapping/article
//结果:
{
  "forum": {
    "mappings": {
      "article": {
        "properties": {
          "articleID": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "hidden": {
            "type": "boolean"
          },
          "postDate": {
            "type": "date"
          },
          "userID": {
            "type": "long"
          }
        }
      }
    }
  }
}

重点解释:
在5.2版本以后type=text时会默认两个field,一个是field本身,比如articleID,就是分词的;另一个是field.keyword,articleID.keyword,默认不分词,会最多保留256个字符。

2. filter执行原理:bitset机制与caching机制

2.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.2 为每个倒排索引中搜索到的结果构建一个bitset

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

2.3 遍历每个过滤条件对应的bitset,优先从最稀疏的开始搜索

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

2.4 caching bitset

跟踪query,在最近256个query中超过一定次数的过滤条件,缓存其bitset。这样下次如果再有这个条件过来的时候,就不用重新扫描倒排索引,反复生成bitset,可以大幅度提升性能。

filter针对小segment获取到的结果,可以不缓存,segment记录数<1000,或者segment大小

2.5 filter相对query的优势

  1. filter比query的好处就在于会caching,但是之前不知道caching的是什么东西,实际上并不是一个filter返回的完整的doc list数据结果。而是filter bitset缓存起来。下次不用扫描倒排索引了。
  2. query:是会计算doc对搜索条件的relevance score,还会根据这个score去排序
    filter:只是简单过滤出想要的数据,不计算relevance score,也不排序
    所以filter大部分情况下来说,在query之前执行,先尽量过滤掉尽可能多的数据
  3. 如果document有新增或修改,那么cached bitset会被自动更新
  4. 以后只要是有相同的filter条件的,会直接来使用这个过滤条件对应的cached bitset

3. 使用terms搜索多个值,相当于sql中in

3.1 为帖子字段添加tag字段

POST /forum/article/_bulk
{ "update": { "_id": "1"} }
{ "doc" : {"tag" : ["java", "hadoop"]} }
{ "update": { "_id": "2"} }
{ "doc" : {"tag" : ["java"]} }
{ "update": { "_id": "3"} }
{ "doc" : {"tag" : ["hadoop"]} }
{ "update": { "_id": "4"} }
{ "doc" : {"tag" : ["java", "elasticsearch"]} }

3.2 搜索articleID为KDKE-B-9947-#kL5或QQPX-R-3956-#aD8的帖子

GET /forum/article/_search 
{
  "query": {
    "constant_score": {
      "filter": {
        "terms": {
          "articleID": [
            "KDKE-B-9947-#kL5",
            "QQPX-R-3956-#aD8"
          ]
        }
      }
    }
  }
}

3.3 优化terms多值搜索

如果我们只想搜索tag中只包含java的帖子,可以先指定tag的长度

POST /forum/article/_bulk
{ "update": { "_id": "1"} }
{ "doc" : {"tag_cnt" : 2} }
{ "update": { "_id": "2"} }
{ "doc" : {"tag_cnt" : 1} }
{ "update": { "_id": "3"} }
{ "doc" : {"tag_cnt" : 1} }
{ "update": { "_id": "4"} }
{ "doc" : {"tag_cnt" : 2} }

//然后搜索
GET /forum/article/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "tag_cnt": 1
              }
            },
            {
              "terms": {
                "tag": ["java"]
              }
            }
          ]
        }
      }
    }
  }
}

4. 基于range filter来进行范围过滤

4.1 为帖子数据增加浏览量的字段

POST /forum/article/_bulk
{ "update": { "_id": "1"} }
{ "doc" : {"view_cnt" : 30} }
{ "update": { "_id": "2"} }
{ "doc" : {"view_cnt" : 50} }
{ "update": { "_id": "3"} }
{ "doc" : {"view_cnt" : 100} }
{ "update": { "_id": "4"} }
{ "doc" : {"view_cnt" : 80} }

4.2 搜索浏览量在30~60之间的帖子

GET /forum/article/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "range": {
          "view_cnt": {
            "gt": 30,
            "lt": 60
          }
        }
      }
    }
  }
}

4.3 搜索发帖日期在最近1个月的帖子

POST /forum/article/_bulk
{ "index": { "_id": 5 }}
{ "articleID" : "DHJK-B-1395-#Ky5", "userID" : 3, "hidden": false, "postDate": "2017-03-01", "tag": ["elasticsearch"], "tag_cnt": 1, "view_cnt": 10 }

//查询指定日期范围内
GET /forum/article/_search 
{
  "query": {
    "constant_score": {
      "filter": {
        "range": {
          "postDate": {
            "gt": "2017-03-10||-30d"
          }
        }
      }
    }
  }
}

//查询最近日期范围
GET /forum/article/_search 
{
  "query": {
    "constant_score": {
      "filter": {
        "range": {
          "postDate": {
            "gt": "now-30d"
          }
        }
      }
    }
  }
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页