【问题标题】:How to index and query Nested documents in the Elasticsearch如何在 Elasticsearch 中索引和查询嵌套文档
【发布时间】:2019-12-25 17:50:09
【问题描述】:

我在 Postgres 表中有 100 万用户。它有大约 15 个不同数据类型的列(如整数、字符串数组、字符串)。目前根据我的要求使用普通的 SQL 查询来过滤数据。

每个用户下还有“N”个项目(最多 5 个项目)。我已经在弹性搜索中索引了这些项目并进行了模糊搜索。目前,对于每个项目(文本文件),我在 elasticsearch 中创建了一个文档。

两个系统都运行良好。

现在我需要查询两个系统上的数据。例如:我想要所有具有关键字 java(在 elasticsearch 上)和 experience 超过 10 年的记录(在 Postgres 中可用)。

由于用户数量将急剧增加,我已将所有 Postgres 数据移至 elasticsearch。

有可能只对与用户相关的字段(项目相关字段除外)应用过滤器。

现在我需要为相应的用户创建嵌套项目。我尝试了父子类型,但对我不起作用。

谁能帮我解决以下问题?

  • 索引与用户相关的项目的正确方法是什么?
  • 由于每个项目文档都有一个名为 category 的字段,是否可以在响应中获取匹配的类别名称?
  • 还有其他更好的方法来实现吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    根据您的描述,我们可以看出“基础文档”都是基于用户的。

    现在,关于您的问题:

    1. 根据我之前所说,您可以将与每个用户关联的所有项目添加为一个数组。像这样:

    {
        "user_name": "John W.",
        ..., #More information from this user
        "projects": [
            {
                "project_name": "project_1",
                "role": "Dev",
                "category": "Business Intelligence",                
            },
            {
                "project_name": "project_3",
                "role": "QA",
                "category": "Machine Learning",
            }
        ]
    },
    {
        "user_name": "Diana K.",
        ..., #More information from this user
        "projects": [
            {
                "project_name": "project_1"
                "role": "Project Leader",
                "category": "Business Intelligence",
    
            },
            {
                "project_name": "project_4",
                "role": "DataBase Manager",
                "category": "Mobile Devices",
            },
            {
                "project_name": "project_5",
                "role": "Project Manager",
                "category": "Web services",
            }
        ]
    }
    

    这个结构的目的是将用户的所有信息添加到每个文档中,如果信息重复则无关紧要。例如,这样做可以让您恢复在特定项目中工作的所有用户,例如:

    {
        "query":{
            "match": {
                "projects.name": "project_1"
            }
        }
    }
    
    1. 是的。与上面的查询一样,您可以通过“类别”字段匹配所有项目。但是,请记住,由于您的基础文档仅与用户相关,因此它将带回整个用户的文档。

    在这种情况下,您可能需要使用Terms aggregation,它将为您带来某些字段的唯一值。这可以与查询“组合”。像这样:

    {
        "query":{
            "match": {
                "projects.category": "Mobile Devices"
            }
        }
    },
    "size", 0 #Set this to 0 since you want to focus on the aggregation's result.
    {
        "aggs" : {
            "unique_projects_names" : {
                "terms" : { "field" : "projects.name" } 
            }
        }
    }
    

    最后一个查询将在聚合字段中返回所有具有“移动设备”类别的唯一项目名称。

    1. 您可以创建一个新索引来存储与您的项目相关的所有信息。但是,用户和项目之间的关系不容易保持(请记住,ES 不适合作为结构化数据库或 ER DB,如 SQL)并且查询将变得非常复杂,即使您决定将两者都命名为索引(用户和项目),您可以使用通配符调用它们。

    编辑:另外,您可以考虑将与您的项目相关的所有信息存储在 Postgress 中并单独进行调用,首先从 ES 获取项目 ID(或名称),然后从 Postgres 获取项目的信息(因为我假设可能是更可能不会改变的信息)。

    希望这有帮助! :D

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      相关资源
      最近更新 更多