6

我是“弹性搜索”的新手,目前正试图了解 ES 如何保持“父子”关系。我从以下文章开始:

https://www.elastic.co/blog/managing-relations-inside-elasticsearch

但是这篇文章是基于旧版本的 ES 的,我目前使用的是 ES 7.5,它指出:

_parent 字段已被删除,取而代之的是 join 字段。

现在我正在关注这篇文章:

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/parent-join.html

但是,我无法获得预期的结果。

我有一个场景,其中我有两个索引“Person”和“Home”。每个“人”可以有多个“家”,这基本上是一对多的关系。问题是当我查询以获取父母为“XYZ”人的所有房屋时,答案为空。

以下是我的索引结构和搜索查询:

人物指数:

请求网址:http://hostname/person

{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            },
            "person_home": {
                "type": "join",
                "relations": {
                    "person": "home"
                }
            }
        }
    }
}

主页索引:

请求网址:http://hostname/home

{
    "mappings": {
        "properties": {
            "state": {
                "type": "text"
            },
            "person_home": {
                "type": "join",
                "relations": {
                    "person": "home"
                }
            }
        }
    }
}

在人员索引中添加数据

请求网址:http://hostname/person/_doc/1

{
    "name": "shujaat",
    "person_home": {
        "name": "person"
    }
}

在主页索引中添加数据

请求网址:http://hostname/home/_doc/2?routing=1&refresh

{
    "state": "ontario",
    "person_home": {
        "name": "home",
        "parent": "1"
    }
}

查询获取数据:(获取所有父为 person id "1" 的记录)

请求网址:http://hostname/person/_search

   {
    "query": {
        "has_parent": {
            "parent_type": "person",
            "query": {
                "match": {
                    "name": "shujaat"
                }
            }
        }
    }
}

或者

{
    "query": {
        "has_parent": {
            "parent_type": "person",
            "query": {
                "match": {
                    "_id": "1"
                }
            }
        }
    }
}

回复:

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    }
}

我无法理解我在这里缺少什么或上述查询有什么问题,因为它没有返回任何数据。

4

1 回答 1

8

您应该将父文档和子文档放在同一个索引中

连接数据类型是一个特殊字段,它在同一索引的文档中创建父/子关系。

因此映射如下所示:

PUT http://hostname/person_home
{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            },
            "state": {
                "type": "text"
            },
            "person_home": {
                "type": "join",
                "relations": {
                    "person": "home"
                }
            }
        }
    }
}

请注意,它具有原始字段personhome索引中的两个字段。

您的其余代码应该可以正常工作。尝试将personhome文档插入到同一索引person_home中,并使用您在问题中发布的查询。

如果personhome对象具有重叠的字段名称怎么办?

假设两种对象类型都有字段name,但我们想分别索引和查询它们。在这种情况下,我们可以提出这样的映射:

PUT http://hostname/person_home
{
    "mappings": {
        "properties": {
            "person": {
                "properties": {
                    "name": {
                        "type": "text"
                    }
                }
            },
            "home": {
                "properties": {
                    "name": {
                        "type": "keyword"
                    },
                    "state": {
                        "type": "text"
                    }
                }
            },
            "person_home": {
                "type": "join",
                "relations": {
                    "person": "home"
                }
            }
        }
    }
}

现在,我们应该改变对象本身的结构:

PUT http://hostname/person_home/_doc/1
{
    "name": "shujaat",
    "person_home": {
        "name": "person"
    }
}

PUT http://hostname/person_home/_doc/2?routing=1&refresh
{
    "home": {
        "name": "primary",
        "state": "ontario"
    },
    "person_home": {
        "name": "home",
        "parent": "1"
    }
}

如果您必须将旧数据从两个旧索引迁移到新的合并索引中,则可能会使用reindex API 。

于 2020-01-23T12:51:34.043 回答