首页 > 解决方案 > 如何在 Elasticsearch 中索引和查询嵌套文档

问题描述

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

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

两个系统都运行良好。

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

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

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

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

谁能帮我做以下事情?

标签: elasticsearch

解决方案


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

现在,关于您的问题:

  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. 是的。与上面的查询一样,您可以通过“类别”字段匹配所有项目。但是,请记住,由于您的基础文档仅与用户相关,因此它将带回整个用户的文档。

对于这种情况,您可能需要使用术语聚合,它会为您带来某些字段的唯一值。这可以与查询“组合”。像这样:

{
    "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


推荐阅读