Elasticsearch实战(第2版)
上QQ阅读APP看书,第一时间看更新

2.4 词项级查询

Elasticsearch拥有一种专门的查询类型——词项级查询,用于支持查询结构化数据。数值、日期、范围、IP地址等属于结构化文本类型。Elasticsearch对待结构化数据和非结构化数据的方式有所不同:非结构化(全文)数据会被分析,而结构化字段则按原样存储。

让我们回顾一下图书文档,看一下 edition、amazon_rating和release_date字段(在代码清单2-15中用粗体展示)。

代码清单2-15 一个样本图书文档

{
  "title": "Effective Java",
  "author": "Joshua Bloch",
  "synopsis": "A must-have book for every Java programmer and Java, ...",
  "edition": 3,
  "amazon_rating": 4.7,
  "release_date": "2017-12-27",
  ...
}

当我们第一次索引文档时,由于我们没有预先创建索引,Elasticsearch会通过分析字段的值来推断出模式。例如,edition字段被表示为数值(非文本)字段,因此会被引擎推断为long数据类型。

按照类似的逻辑,amazon_rating字段被确定为float数据类型,因为该字段包含小数。release_date被确定为date数据类型,因为这个值以国际标准ISO 8601的日期格式(yyyy-MM-dd)表示。这3个字段都被归类为非文本(non-text)字段,这意味着它们的值不会被分词(不会被拆分成词元),也不会被归一化(没有同义词或词根),而是按原样存储。

词项级查询只会产生两种输出:如果查询与条件相匹配,则返回结果;否则,不返回任何结果。这些查询不考虑文档的匹配程度(相关性),而是专注于查询是否有匹配。由于不考虑相关性,因此词项级查询不会产生相关性分数。在本节中我们看几个词项级查询的例子。

2.4.1 term查询

term查询用于获取与搜索条件中提供的值精确匹配的结果。例如,要获取所有第3版的书,我们可以编写一个term查询,如代码清单2-16所示。

代码清单2-16 获取第3版的书

GET books/_search
{
  "_source": ["title","edition"],  ←---  在响应文档中只返回两个字段
  "query": {
    "term": {  ←---  声明这是一个词项级查询
      "edition": {  ←---  提供字段和值作为搜索条件
        "value": 3
      }
    }
  }
}

这个查询返回了所有第3版的书(我们的索引中只有1本书,即Effective Java),如下所示:

"hits" : [{
  ...
  "_score" : 1.0,
  "_source" : {
    "title" : "Effective Java",
    "edition" : 3,
    ...
  }
}]

如果仔细观察结果你会发现,结果的默认分数是1.0,就像我之前提到的,词项级查询并不关心相关性。

2.4.2 range查询

range查询用于获取匹配某个范围的结果,例如获取从凌晨1:00到下午1:00之间的航班,或者找到年龄在14岁到19岁之间的青少年。range查询是搜索范围数据的强大工具,可以应用于日期、数值和其他属性。

继续图书的例子。我们可以使用range查询来获取所有amazon_rating高于或等于4.5星且低于或等于5星的书,如代码清单2-17所示。

代码清单2-17 使用range查询获取评分在4.5星到5星之间的书

GET books/_search
{
  "query": {
    "range": {  ←---  声明range查询
      "amazon_rating": {  ←---  匹配的范围
        "gte": 4.5,  ←---  gte:大于或等于
        "lte": 5  ←---  lte:小于或等于
      }
    }
  }}

这个range查询将获取3本书,因为有3本书的评分高于或等于4.5星(为简洁起见,省略了输出结果)。

还有几种词项级查询,包括terms查询、ids查询、exists查询、prefix查询等。我将在第8~10章中更详细地介绍这几种词项的查询。

到目前为止,我已经介绍了一些根据基本条件获取结果时可能有用的查询,例如匹配书名、在多个字段中搜索一个单词、查找评分最高的书等。但实际上,查询可能更复杂,例如获取Joshua撰写的评分高于4.5星且于2015年后出版的第1版的书。幸运的是,Elasticsearch提供了高级查询类型,以便我们可以使用这些高级查询以复合查询(compound query)的方式来满足复杂的搜索条件。下面我们就来看一个复合查询的例子。