如何以自定义方式组合多个稀疏、密集和地理字段
Elasticsearch 是一个可扩展的数据存储和向量数据库,功能强大,可用于近乎实时地搜索和分析数据。作为开发人员,我们经常遇到包含各种类型不同字段的数据集。有些字段是必填的或包含比平均值更多的填充数据,而其他字段则几乎没有填充。缺少值的字段称为“稀疏”字段,而大多数值都存在的字段称为“密集”字段。当然,我们还有那些表示地理位置数据的地理字段。
在本文中,我们将了解如何查询包含不同字段的数据。我们将探索稀疏、密集和地理字段的集成,以增强您的搜索功能。我们将逐步完成动手示例(使用我最喜欢的books
索引 :)),通过 Kibana DevTools 将样本数据导入 Elasticsearch,并执行词汇和地理搜索。
在我们深入了解如何组合这些字段以提取更深入的分析功能的细节之前,让我们先定义这些字段。
稀疏字段
稀疏字段是指并非每个文档中都存在的字段。
例如,考虑books
索引,其中包含各种类型的书籍。我们books
索引中的special_edition
字段是稀疏的,因为并非所有书籍都作为特别版发行。类似地,可能还有其他字段,例如category
或sales_info
,这些字段可能并非对所有书籍都可用。稀疏字段可用于根据数据集子集拥有的属性过滤结果。
密集字段
相反,密集字段是指预期出现在所有或大多数文档中的字段。例如,我们books
索引中的title
、author
、number_of_pages
和publication_date
字段被认为是密集字段。它们对大多数(如果不是全部)书籍都可用,并且是每个文档的核心。它们有助于提供可靠的搜索查询。
地理字段
地理字段允许索引地理数据,从而能够根据位置或地理区域进行搜索。在我们的books
索引中,topic_location
是一个地理字段,可以表示各种基于位置的属性。例如,作者的位置,书籍原始印刷的地方等。
组合不同的字段
以自定义方式组合这些字段可以显著增强搜索功能并提供更相关的结果。在许多用例中,我们希望查询稀疏填充字段与密集字段以及地理字段的组合。
Elasticsearch 的强大功能在于它能够处理组合各种数据类型的复杂查询。通过了解稀疏、密集和地理位置字段的特点,我们可以制定针对特定用户需求的集中搜索查询。
让我们看看如何通过运行动手示例来处理不同的数据字段。
创建“books”索引
首先,让我们定义一个books
索引,其中包含适用于在线书店的各种字段类型。
如下面的 PUT 请求所示,books
索引的映射包含一些标准的书籍属性。但是,您还可以找到一些可能不适用于每本书的字段,例如
available_copies
special_edition
这些属性被认为是稀疏的,因为它们并不一定需要为每本书填充。其他字段title
、author
、publication_date
等字段预计每个(或大多数)书籍都会存在。
并且我们希望将这些字段与一个地理点字段组合起来,该字段可以表示书籍主题的位置
# Creating books mapping schema
PUT /books
{
"mappings": {
"properties": {
"title": { "type": "text" },
"author": { "type": "text" },
"price": { "type": "float" },
"tags": { "type": "keyword" },
"publication_date": { "type": "date" },
"available_copies": { "type": "integer" },
"special_edition": { "type": "boolean" },
"topic_location": { "type": "geo_point" },
"genre": { "type": "keyword" },
"language": { "type": "keyword" }
}
}
}
上面的代码片段向我们展示了books
索引的映射模式。它包含各种字段的混合——稀疏、密集和地理位置字段。
复制代码片段并将其粘贴到 Kibana 控制台中。执行它将创建我们的books
索引。
现在我们已经创建了映射,让我们索引一些示例数据。
索引示例数据
我们希望索引一些包含代表我们需求的数据的书籍。以下示例文档添加了包含这些属性混合的书籍
# Omitting special_edition and technology
# Note the location is Silicon Valley
POST /books/_doc/1
{
"title": "Head First Java: A Brain-Friendly Guide",
"author": " Kathy Sierra, Bert Bates, Trisha Gee",
"price": 43.99,
"tags": ["programming", "Java", "advanced"],
"publication_date": "2024-03-20",
"available_copies": 10,
"topic_location": { "lat": 37.3861, "lon": -122.0839 },
"genre": "Technology",
"language": "English",
"technology": "Java"
}
# Omitting 'special_edition'
# Note the location is London
POST /books/_doc/2
{
"title": "Elasticsearch in Action 2e",
"author": "Madhusudhan Konda",
"price": 39.99,
"tags": ["Elasticsearch", "Search", "Technology", "2nd Edition"],
"publication_date": "2022-07-01",
"available_copies": 10,
"topic_location": { "lat": 51.5074, "lon": -0.1278 },
"genre": "Technology",
"special_edition": true,
"language": "English",
"technology": "Elasticsearch"
}
# Omitting 'available_copies', 'special_edition', and 'topic_location'
POST /books/_doc/3
{
"title": "Functional Programming in Java",
"author": "Venkat Subramaniam",
"price": 36.99,
"tags": ["Java", "Functional Programming", "Software Development"],
"publication_date": "2018-03-15",
"genre": "Technology",
"language": "English",
"technology": "Java"
}
如您所见,我们有四本不同的书籍,每本书都索引了一些缺少的字段——从而演示了稀疏字段的概念。
在完成数据准备后,下一步是有效地编写查询,使这些不同的字段产生出色的分析见解。
我们将编写以下查询
- 查找特定位置附近的 Java 书籍
- 获取特别版搜索技术书籍
- 搜索多种语言的最新 IT 书籍
本文的其余部分解释了如何创建组合稀疏、密集和地理字段的查询。
查找科技中心附近的 Java 书籍
假设我们想查找特定位置(例如 SFO)附近可用的 Java 书籍。我们希望编写一个bool
查询以匹配地理区域内的 Java 书籍。以下查询可以完成此任务
在这里,我们寻找硅谷附近的与 Java 相关的书籍
# Searching for Java books in Silicon Valley
GET /books/_search
{
"query": {
"bool": {
"must": [
{ "match": { "technology": "Java" } }
],
"filter": [
{ "geo_distance": { "distance": "100km", "topic_location": { "lat": 37.7749, "lon": -122.4194 } } }
]
}
}
}
执行此查询将返回“硅谷”附近或周围的“Java”书籍——大约 100 公里的半径。在这种情况下,将返回“Head First Java”。
该查询组合了字段类型以实现目标搜索目标。该查询查找与“Java”(一个technology
字段)特别相关的书籍,该字段可能与索引中所有条目都不相关。这是一种稀疏字段场景,因为并非所有书籍都填充了technology
字段。
此示例演示了 Elasticsearch 如何将不同的数据类型集成到一个连贯的搜索策略中。
查询特别版搜索技术书籍
假设我们的目标是识别数据库中属于特别版书籍并且与搜索技术(如 Elasticsearch)相关的书籍。此查询提取可能与对深入了解该技术感兴趣的特定受众特别相关的书籍。
我们再次使用bool
查询来过滤与搜索技术相关的特别版书籍
# Special edition Technology books
GET /books/_search
{
"query": {
"bool": {
"must": [
{ "match": { "special_edition": true } },
{ "match": { "technology": "Elasticsearch" } }
],
"should": [
{ "match": { "language": "English" } }
],
"must_not": [
{ "range": { "publication_date": { "lt": "2015-01-01" } } }
],
"minimum_should_match": 1
}
}
}
此查询根据special_edition
字段(稀疏)和genre
字段(密集)过滤书籍。由于genre
是可能存在于每本图书文档中的字段,因此该查询变得更普遍地适用于整个数据集,使其成为一个密集字段。
除了上述要求外,我们还希望书籍以英语出版(尽管由于minimum_should_match
设置为 1,这不是严格的要求)。这意味着如果书籍不是以英语出版的,也不会从搜索结果中排除。但是,如果它们是以英语出版的,则这些书籍在搜索结果中的排名会更高。
为了完整起见,我还添加了must_not
子句——它将排除 2015 年之前出版的书籍。这使我们能够专注于更新的出版物。
从本质上讲,此查询提供了一种平衡的搜索方法
- 使用严格的标准根据书籍的版本和类型进行过滤,
- 设置对英语语言的偏好以提高相关性,以及
- 过滤掉不近期的(2015 年之前出版的)书籍以确保仅包含近期的副本。
搜索多种语言提供的最新 IT 书籍
假设我们的用户可能正在寻找最新的资源(书籍)以保持在科技领域的最新状态,但需要使用其母语(特定)语言提供的材料。这在教育环境、跨国公司或双语人口地区很常见。虽然我不阅读“泰卢固语”(我最初来自印度南部的一种语言 :))的技术书籍,但我了解我的一些朋友希望用他们的母语来解释技术内容。
假设我们想要找到最近同时提供英文和西班牙语版本的 IT 图书,这可能表明其具有更广泛的教育价值。
# Recent IT Books Available in Multiple Languages
GET /books/_search
{
"query": {
"bool": {
"must": [
{ "range": { "publication_date": { "gte": "now-2y" } } }
],
"filter": [
{ "terms": { "language": ["English", "Spanish"] } },
{ "match": { "genre": "Technology" } }
]
}
}
}
让我在“组合/多元”字段的上下文中解释一下这个查询。
publication_date
字段可能是密集字段,因为它是在每条图书记录中都期望的标准属性。通过使用范围查询,我们将注意力集中在过去两年内出版的书籍上。
类似地,genre
在图书数据库中通常也是密集字段,因为书籍通常被分类为不同的类型。该查询过滤了专门属于“科技”类型的书籍。这确保了与 IT 主题相关的相关书籍。
language
字段可以被认为是稀疏字段,具体取决于数据集。在全球数据集中,书籍可能有多种语言版本,但并非所有书籍都提供多种语言版本。
通过使用 terms
查询过滤多种语言(在本例中为英语和西班牙语),我们正在获取满足多种语言受众的书籍。
总结
就是这样。在这篇文章中,我们学习了不同的数据字段——例如稀疏字段、密集字段和地理字段——以及如何将它们组合起来,以便对我们的数据进行深入分析。
Elasticsearch 拥有众多新功能,可帮助您构建最适合您用例的搜索解决方案。深入了解我们的 示例笔记本 以了解更多信息,开始 免费云试用,或立即在您的 本地机器 上试用 Elastic。
想要获得 Elastic 认证?了解下一场 Elasticsearch 工程师培训 什么时候开始!