如何在ElasticSearch中对层次结构进行非规范化?

时间:2017-10-17 12:38:35

标签: elasticsearch hierarchical-data denormalization

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

我的源数据存储在SQL Server中,架构看起来像这样: enter image description here

通过将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 }}
            ]
        }
    }
}'

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

1 个答案:

答案 0 :(得分:1)

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

从您给出的示例中,我将索引表单的文档:

path

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

  • 字段text
  • 字段text

配置索引映射和分析以拆分typesmatch_phrase字段,然后使用a或

  1. 向我提供所有type2-> type3路径types字段上使用match查询
  2. 路径包含X 使用path字段上的term查询
  3. 其中有4个描述符path.depth子字段上使用{{1}}查询
  4. 你的描述符字段不是很有趣。 对于某些用例,Path tokenizer可能会很有趣。 您可以使用multi-fields在同一字段上应用多个分析器,然后查询子字段。