首页 > 编程笔记 > 通用技能 阅读:2

Elasticsearch nested类型的用法(附带实例)

nested 类型是一种专用的 object 类型形式,它维护了文档中对象数组之间的关系。

举一个电子邮件和附件的示例,我们将 attachments 字段定义为 nested 数据类型,而不是让 Elasticsearch 将其推断为 object 类型。这需要通过声明 attachments 字段为 nested 数据类型来创建模式,示例代码如下:
PUT emails_nested
{
  "mappings": {
    "properties": {
      "attachments": {  ←---  将attachments字段声明为nested类型
        "type": "nested",
        "properties": {
          "filename": {   ←---  将filename字段声明为keyword类型以避免分词
            "type": "keyword"
          },
          "filetype": {
            "type": "text"  ←---  将该字段保留为text类型
          }
        }
      }
    }
  }
}
除了将 attachments 字段创建为 nested 类型,我们还将 filename 声明为 keyword 类型。filename 字段的值会被分词,例如 file1.txt 被拆分成 file1 和 txt。因此,搜索查询可能与 txt 和 confidential 或 txt 和 private 匹配,因为这两条记录都有 txt 作为公共的词元。为了避免这种情况,我们可以将 filename 作为 keyword 类型的字段。

我们已经有了模式定义,需要做的就是索引一个文档,示例代码如下:
PUT emails_nested/_doc/1
{
  "attachments" : [  ←---   提供几个对象作为附件
    {
      "filename" : "file1.txt",
      "filetype" :  "confidential"
    }
    {
      "filename" : "file2.txt",
      "filetype" :  "private"
    }
  ]
}

一旦该文档成功索引,拼图的最后一块就是搜索。下面的示例代码展示了用于获取文档的搜索查询,搜索条件是带有附件的电子邮件,其中文件名和文件分类分别为 file1.txt 和 private。因为这种组合不存在,所以结果一定为空,这与使用 object 类型的情况不同,使用 object 类型时,数据是跨文档搜索的,会导致假阳性结果。
GET emails_nested/_search
{
  "query": {
    "nested": {   ←---  使用nested查询搜索nested字段中的数据
      "path": "attachments",   ←---  指向nested字段的路径
      "query": {
        "bool": {
          "must": [   ←---  搜索子句:必须匹配file1.txt和private
            { "match": { "attachments.filename": "file1.txt" }},
            { "match": { "attachments.filetype":  "private" }}
          ]
        }
      }
    }
  }
}
该查询搜索名为 file1.txt 且分类为 private 的文件,这样的文件并不存在。这个查询没有返回任何文档,这正是我们所期望的。file1.txt 的分类是 confidential,不是 private,因此它不匹配。当 nested 类型表示一个内部对象的数组时,每个单独的对象都被存储和索引为一个隐藏的文档。

nested 数据类型擅长维护关联和关系。如果需要创建对象数组,而每个对象都必须被视为一个单独的对象,那么 nested 数据类型可能是好的选择。

相关文章