【问题标题】:How to denormalize hierarchy in ElasticSearch?如何在 ElasticSearch 中对层次结构进行非规范化?
【发布时间】:2018-03-29 03:45:57
【问题描述】:

我是 ElasticSearch 的新手,我有一棵树,它描述了某个文档的路径(不是真正的文件系统路径,只是将文章、图像、文档分类为一个的简单文本字段)。每个路径条目都有一个类型,例如:Group NameAssembly name 甚至 Unknown。例如,可以在查询中使用这些类型来跳过路径中的某些条目。

我的源数据存储在 SQL Server 中,架构如下所示:

通过将Tree.Id 连接到Tree.ParentId 来构建树,但每个节点都必须有一个类型。文档与树中的叶子相连。

我不担心在 SQL Server 中查询结构,但是我应该找到一种最佳方法来非规范化并在 Elastic 中搜索它们。如果我将路径展平并为文档制作“描述符”列表,我可以将每个文档条目存储为弹性文档。:

{
  "path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
  "descriptors": [
    {
      "name": "NodeNameRoot",
      "type": "type1"
    },
    {
      "name": "NodeNameLevel_1",
      "type": "type1"
    },
    {
      "name": "NodeNameLevel_2",
      "type": "type2"
    },
    {
      "name": "NodeNameLevel_3",
      "type": "type2"
    },
    {
      "name": "NodeNameLevel_4",
      "type": "type3"
    }
  ],
  "document": {
    ...
  }
}

我可以在 ElasticSearch 中查询这样的结构吗?或者我应该以不同的方式对路径进行非规范化吗?

我的主要问题:

可以根据类型或文本值查询它们(例如正则表达式匹配)。例如:给我所有的 type2->type3 路径(实际上将 type1 排除在外),其中路径包含X?

可以根据等级查询吗?就像我想要有 4 个描述符的路径。

我可以使用内置功能进行搜索还是需要编写扩展程序?

编辑 基于 G Quintana 的 anwser,我做了一个这样的索引。:

curl -X PUT \
  http://localhost:9200/test \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
  "mappings": {
    "path": {
      "properties": {
        "names": {
          "type": "text",
          "fields": {
            "raw": {
              "type": "keyword"
            },
            "tokens": {
              "type": "text",
              "analyzer": "pathname_analyzer"
            },
            "depth": {
              "type": "token_count",
              "analyzer": "pathname_analyzer"
            }
          }
        },
        "types": {
          "type": "text",
          "fields": {
            "raw": {
                "type": "keyword"
            },
            "tokens": {
                "type": "text",
                "analyzer": "pathname_analyzer"
            }
          }
        }
      }
    }
  },
  "settings": {
    "analysis": {
      "analyzer": {
        "pathname_analyzer": {
          "type": "pattern",
          "pattern": "#->>",
          "lowercase": true
        }
      }
    }
  }
}'

并且可以像这样查询深度。:

curl -X POST \
  http://localhost:9200/test/path/_search \
  -H 'content-type: application/json' \
  -d '{
    "query": {
        "bool": {
            "should": [
                {"match": { "names.depth": 5 }}
            ]
        }
    }
}'

返回正确的结果。我会再测试一下。

【问题讨论】:

    标签: elasticsearch hierarchical-data denormalization


    【解决方案1】:

    首先,您应该确定所有查询模式,以设计如何索引数据。

    从您给出的示例中,我将索引以下形式的文档:

    {
      "path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
      "types: "type1/type1/type2/type2/type3",
      "document": {
        ...
      }
    }
    

    在建立索引之前,必须配置映射和分析:

    • 字段path:
    • 字段types

    配置索引映射和分析以拆分 pathtypes 字段以及使用 a 或 a

    1. 给我所有 type2->type3 路径types 字段上使用 match_phrase 查询
    2. 路径包含 Xpath 字段上使用 match 查询
    3. 其中有 4 个描述符path.depth 子字段上使用 term 查询

    您的描述符字段并不有趣。 Path tokenizer 对于某些用例可能很有趣。 您可以使用multi-fields在同一字段上应用多个分析器,然后查询是否有子字段。

    【讨论】:

    • 我用您建议的解决方案编辑了我的问题。它似乎有效,但我想知道你是否也会这样做。
    • 另外,为了实现If at depth n field's text matches X,我应该引入另一个字段,它具有指向节点文本的级别,例如"0":"NodeNameRoot""3":"NodeNameLevel_3"
    猜你喜欢
    • 2016-06-20
    • 1970-01-01
    • 2017-09-06
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 2015-07-14
    相关资源
    最近更新 更多