驽马十驾 驽马十驾

驽马十驾,功在不舍

目录
【ELK】结构化搜索
/  

【ELK】结构化搜索

搜索从得分上来说可以分为 2 类,需要搜索得分和不需要搜索得分。

搜索得分可以看做是匹配度的高低,对于“固定值”的搜索而言,通常不需要计算得分。其好处可以进行缓存,同时减轻服务器计算压力。

本章内容就是讲述固定值的搜索:Term 查询、范围 Range 查询、空值判定 Exists、

Term 查询通常用于:Keyword 关键字,Bool 类型,Date日期类型、Number 数值类型等的查询

数据准备

按照流程:创建索引、新建映射、插入文档数据的步骤进行

# 删除之前的索引
DELETE /article

# 重建索引
PUT /article

# 设置映射
PUT /article/_mapping
{
  "properties": {
    "articleID": {
      "type": "keyword"
    }
  }
}

# 查看映射
GET /article/_mapping

# 批量添加数据
POST 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-04" }
{ "index": { "_id": 3 }}
{ "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-05-01"}
{ "index": { "_id": 4 }}
{ "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-03-02" }

通过上述操作后,可以通过如下形式查询所有的结果来检验下数据是否插入进去。

GET /article/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 50
}

Term查询

语法案例

以下是一组2 种 term 的通用等价写法,其中avaliable是一个bool类型的字段。

image.png

单字段匹配

上述代码中我们仅仅手动设置了 articleIDkeyword ,所以可以可以通过获取 Mapping 来确定当前文档的定义。

GET /article/_mapping

结果是

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

可以看出字段的类型为:keyword/boolean/date/long 这些类型都是可以通过 term 进行查询的。

首先来一个简答的根据 userID 进行查询

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

大体结构是:query -> constant_score -> filter -> term -> filed

同理 Term 支持 当前这个文档每个字段的查询

GET /article/_search
{"query":{"constant_score":{"filter":{"term":{"postDate":"2017-01-02"}}}}}

其他类似,不做赘述。

Term查询只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分。因为在查询时,不需要计算评分,因此采用constant_score寻找的方式速度会更快。

如果一个查询只有filter过滤条件,可以用constant_score来替代bool查询,这样的查询语句更简洁、更清晰,只是没有评分。

多字段匹配

GET /article/_search
{
  "query": {
    "bool": {
      "filter": [ #此处 filter 也可以改为 must,案例3
        {
          "term": {
            "userID": "1"
          }
        },
        {
          "term": {
            "postDate": "2017-01-02"
          }
        }
      ]
    }
  }
}

以下这个写法是错误的,会提示:"[term] query doesn't support multiple fields, found [userID] and [postDate]"

GET /article/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "userID": "1",
          "postDate": "2017-01-02"
        }
      }
    }
  }
}

感觉下面的理解更好:query -> bool -> must

GET /article/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "userID": "1"
          }
        },
        {
          "term": {
            "postDate": "2017-01-02"
          }
        }
      ]
    }
  }
}

bool 查询中 filtered 的用法已经被淘汰,推荐更换为 bool 用法。

单字段 In

GET /article/_search
{
  "query": {
    "terms": {
      "postDate": ["2017-01-01","2017-01-02"]
    }
  }
}

GET /article/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "terms": {
            "postDate": ["2017-01-01","2017-01-02"]
        }
      }
    }
  }
}

对于 terms 这样的等值匹配,感觉使用 constant_score + filter是没有效果的,上述案例的写法 1写法 2 效果相同。

数字 range

GET /article/_search
{
  "query": {
    "range": {
      "postDate": {
        "gte":"2017-01-01",
        "lt": "2018-01-01"
      }
    }
  }
}
  • gte 表示大于等于
  • gt 表示大于
  • lte 表示小于等于
  • lt 表示小于

存在判定Exists

可以理解为 SQL中的 where postDate is not null

GET /article/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "exists": {
          "field": "postDate"
        }
      }
    }
  }
}
骐骥一跃,不能十步。驽马十驾,功在不舍。