Elasticsearch 字段多种类型处理

背景
 
在搜索引擎和数据存储中,高效处理多样化的查询需求至关重要。以公司名称和时间字段为例,这些字段可能需要同时支持全文搜索和精确匹配。Elasticsearch 提供了多字段功能,允许单个字段展示多种行为,例如分词搜索和精确匹配。本文将分析如何利用多字段功能,处理具有多种类型需求的字段,如 name 和时间字段。
多字段基础
 
在 Elasticsearch 中,一个字段无法具备多种类型,但通过 多字段机制 (Multi-fields),同一个字段可以有多种功能,如全文搜索和精确匹配。
尽管一个字段只能有一个主类型,但通过属性 fields,可以为字段增加子字段,每个子字段可以有自己的类型和属性。
基本示例
 
下面是一个多字段的配置:
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",  // 主字段,用于全文搜索
        "fields": {
          "keyword": { // 子字段名
            "type": "keyword",  // 子字段,用于精确匹配
            "ignore_above": 256
          }
        }
      }
    }
  }
}

 

name 字段应用场景
 
想象一个情况:在一个全球化的应用中,需要搜索公司名称,比如“Dragon Ball Co., Ltd.”:
需求分析
 
1.
支持全文搜索:
用户不许能输入全部名称,但输入“Dragon” 或 “Ball”,应该返回有关的文档。
 
2.
支持精确匹配:
实际中需要精确匹配全名“Dragon Ball Co., Ltd.”,应该使用未分词的原始值进行匹配。
 
选择使用多字段
 
  • 全文搜索: 采用主字段 name (类型为 text),支持分词后搜索:
GET dev_companies/_search
{
  "query": {
    "match": {
      "name": "Dragon Ball"
    }
  }
}

 

  • 精确匹配: 采用子字段 name.keyword (类型为 keyword),用于匹配未分词的值:
GET dev_companies/_search
{
  "query": {
    "term": {
      "name.keyword": "Dragon Ball Co., Ltd."
    }
  }
}
  • 短语应匹配: 如果需要匹配分词序列,使用 match_phrase 及远离参数 slop
GET dev_companies/_search { "query": { "match_phrase": { "name": { "query": "Dragon Ball", "slop": 2 } } } }

 

时间字段应用场景

例如,在实际场景中,对时间字段也存在两种需求:
  1. 时间范围搜索:想搜索某个时间范围内的文档。
  2. 原始值保存:想保存原始的时间字符串,便于展示和精确搜索。

选择使用多字段

使用主字段 timestamp 完成时间范围搜索,使用子字段 timestamp.raw 完成原始值匹配。

字段定义

{
  "mappings": {
    "properties": {
      "timestamp": {
        "type": "date",
        "format": "strict_date_optional_time||epoch_millis",  // 支持ISO8601和时间戳
        "fields": {
          "raw": {
            "type": "keyword"  // 子字段,用于保存原始时间字符串
          }
        }
      }
    }
  }
}
timestamp 主字段
  • 类型为 date,适用于时间范围查询(如 range 查询)。
  • 格式支持 ISO8601 格式(strict_date_optional_time)和 Unix 时间戳(epoch_millis)。
timestamp.raw 子字段
  • 类型为 keyword,存储原始时间字符串,适合精确匹配(如 term 查询)。

实现示例

  • 时间范围搜索:
GET my_index/_search
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2025-01-01T00:00:00Z",
        "lte": "2025-12-31T23:59:59Z"
      }
    }
  }
}
  • 精确匹配原始值:
GET my_index/_search
{
  "query": {
    "term": {
      "timestamp.raw": "2025-01-06T12:00:00Z"
    }
  }
}

多字段与多独立字段对比

多字段(Multi-fields)

  • 优点:
    • 数据一致性高,存储在同一个字段下,子字段只是不同的索引方式。
    • 索引管理简单,只需要管理一个字段的映射。
    • 存储空间优化,字段不会重复存储原始数据

  

  • 缺点:
    • 子字段的功能受限,不能自定义存储行为。

  

多独立字段

  • 优点:
    • 每个字段可以完全独立,支持不同的存储规则和查询方式。
    • 灵活性更高,适合复杂场景(如支持多种时间格式)。
  • 缺点:
    • 数据冗余,占用更多存储空间。
    • 索引管理复杂,查询时需要明确字段名称。

选择建议

  • 如果需求涉及 不同字段的多种功能(如不同格式的时间存储和处理),建议使用 多独立字段

    如果需求主要集中在 同一字段的多种查询方式(如全文搜索和精确匹配),建议使用 多字段
posted @ 2025-01-07 10:19  Οo白麒麟оΟ  阅读(216)  评论(0)    收藏  举报