结构化搜索

结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程

在结构化查询中,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。
结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。

精确值查找

当进行精确值查找时, 我们会使用过滤器(filters)。

term 查询 数字

我们首先来看最为常用的 term 查询, 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。

  • 让我们以下面的例子开始介绍,创建并索引一些表示产品的文档,文档里有字段 priceproductID价格产品ID ):
POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }

sql:查找具有某个价格的所有产品

SELECT document FROM   products WHERE  price = 20

DSL:


GET /my_store/products/_search
{
 "query": {"term": {
   "price": {
     "value": "20"
   }
 }}
}

GET /my_store/products/_search
{
 "query": {
   "term": {
   "price": "20"
 }}
}

通常当查找一个精确值的时候,我们不希望对查询进行评分计算。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分

GET /my_store/products/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "price": "20"
        }
      },
      "boost": 1.2
    }
  }  
}

term 查询 文本

sql:

SELECT product FROM   products WHERE  productID = "XHDK-A-1293-#fJ3"

DSL:

GET /my_store/products/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "productID": "XHDK-A-1293-#fJ3"
        }
      },
      "boost": 1.2
    }
  }
}

但这里有个小问题:我们无法获得期望的结果。为什么呢?问题不在 term 查询,而在于索引数据的方式,
如果我们使用 analyze API (分析 API),我们可以看到这里的 UPC 码被拆分成多个更小的 token.

GET /my_store/_analyze
{
  "field": "productID",
  "text": "XHDK-A-1293-#fJ3"
}

{
  "tokens" : [ {
    "token" :        "xhdk",
    "start_offset" : 0,
    "end_offset" :   4,
    "type" :         "<ALPHANUM>",
    "position" :     1
  }, {
    "token" :        "a",
    "start_offset" : 5,
    "end_offset" :   6,
    "type" :         "<ALPHANUM>",
    "position" :     2
  }, {
    "token" :        "1293",
    "start_offset" : 7,
    "end_offset" :   11,
    "type" :         "<NUM>",
    "position" :     3
  }, {
    "token" :        "fj3",
    "start_offset" : 13,
    "end_offset" :   16,
    "type" :         "<ALPHANUM>",
    "position" :     4
  } ]
}

这里有几点需要注意:

  • Elasticsearch 用 4 个不同的 token 而不是单个 token 来表示这个 UPC 。
  • 所有字母都是小写的。
  • 丢失了连字符和哈希符( # )

所以当我们用 term 查询查找精确值 XHDK-A-1293-#fJ3 的时候,找不到任何文档,因为它并不在我们的倒排索引中,正如前面呈现出的分析结果,索引里有四个 token 。

为了避免这种问题,我们需要告诉 Elasticsearch 该字段具有精确值,要将其设置成 not_analyzed 无需分析的

DELETE /my_store 

PUT /my_store
{
  "mappings": {
    "products":{
      "properties": {
        "productID":{
          "type": "keyword"
        }
      }
    }
  }
}

GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "term" : {
                    "productID" : "XHDK-A-1293-#fJ3"
                }
            }
        }
    }
}

组合过滤器

SQL:

SELECT product
FROM   products
WHERE  (price = 20 OR productID = "XHDK-A-1293-#fJ3")
  AND  (price != 30)

DSL:

  • must
    所有的语句都 必须(must) 匹配,与 AND 等价。
  • must_not
    所有的语句都 不能(must not) 匹配,与 NOT 等价。
  • should
    至少有一个语句要匹配,与 OR 等价。
GET /my_store/products/_search
{
   "query" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
   }
}

kyle
23 声望4 粉丝