当前位置: 首页 > 知识库问答 >
问题:

ElasticSearch:孙/子/父关系无法正常工作

林鹭洋
2023-03-14

我在搜索孙子的时候遇到了一些奇怪的弹性搜索行为。我的孙子不能识别每个父文档。当我要求弹性搜索返回父节点的子节点时,它会返回所有可能的命中。然后当我要求归还我那些有大孩子的孩子时,我得到了不正确的结果。有些时候,我没有得到点击或更少。但是当我检查我的孙子的路由和父ID时,我发现他们确实存在于他们的父节点中。但是我不明白为什么我得到的结果不正确。你们中有人遇到过这样的问题吗???我检查了我的代码三次,没有发现任何类型错误:-(让我告诉你重现这个错误的步骤。

以下是我的映射:

PUT/test\u索引

{
   "mappings":{
        "parentDoc":{
            "properties":{
                 "id":{
                    "type":"integer"
                 },
                 "name":{
                    "type":"text"
                    }
                 }
        },
        "childDoc": {
            "_parent": {
                "type": "parentDoc"
            },
            "properties":{
                "id":{
                    "type":"integer"
                },
                "name":{
                   "type":"text"
                },
                "contact": {
                    "type":"text"
                }
            }
        },
        "grandChildDoc": {
            "_parent": {
                "type": "childDoc"
            },
            "properties":{
                "id":{
                    "type":"integer"
                },
                "description":{
                   "type":"text"
                }
            }
        }
    }
}

索引父母Doc:

PUT/test\u索引/parentDoc/1

{
    "pdId":1,
    "name": "First parentDoc"
}

把 /test_index/parentDoc/2

{
    "pdId":2,
    "name": "Second parentDoc"
}

索引子Doc:

放置/测试索引/childDoc/10?父项=1

{
    "cdId":10,
    "name": "First childDoc",
    "contact" : "+XX0000000000"
}

放置/测试索引/childDoc/101?父项=1

{
    "cdId":101,
    "name": "Second childDoc",
    "contact" : "+XX0000000111"
}

把 /test_index/childDoc/20?父母=2

{
    "cdId":20,
    "name": "Third childDoc",
    "contact" : "+XX0011100000"
}

索引孙子:

放置/测试索引/doc/100?父母=10

{
    "gcdId":100,
    "name": "First grandChildDoc"
}

把 /test_index/grandChildDoc/200?家长=10

{
    "gcdId":200,
    "name": "Second grandChildDoc"
}

放置/测试索引/doc/300?家长=20

{
    "gcdId":300,
    "name": "Third grandChildDoc"
}

现在,当我要求弹性搜索向我显示那些有子文档的父文档时,它会返回:POST /test_index/parentDoc/_search

{
    "query": {
        "has_child": {
            "type": "childDoc",
            "query": {
                "match_all": {}
            }
        }
    }
}

结果:(这似乎很好。!)

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1,
        "hits": [
            {
                "_index": "test_index",
                "_type": "parentDoc",
                "_id": "2",
                "_score": 1,
                "_source": {
                    "pdId": 2,
                    "name": "Second parentDoc"
                }
            },
            {
                "_index": "test_index",
                "_type": "parentDoc",
                "_id": "1",
                "_score": 1,
                "_source": {
                    "pdId": 1,
                    "name": "First parentDoc"
                }
            }
        ]
    }
}

现在,当我要求elasticsearch向我显示那些有孙子的儿童医生时,它会返回: POST /test_index/childDoc/_search

{
    "query": {
        "has_child": {
            "type": "grandChildDoc",
            "query": {
                "match_all": {}
            }
        }
    }
}

结果:(在这里,你会注意到一些点击不见了。例如,缺少id为10和101的儿童文档)。

{
    "took": 7,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 1,
        "hits": [
            {
                "_index": "test_index",
                "_type": "childDoc",
                "_id": "20",
                "_score": 1,
                "_routing": "2",
                "_parent": "2",
                "_source": {
                    "cdId": 20,
                    "name": "Third childDoc",
                    "contact": "+XX0011100000"
                }
            }
        ]
    }
}

知道我犯了什么错吗???或者是虫子???任何变通方法或解决方案???

[注:我用的是elasticsearch v5.4]

共有1个答案

冯泓
2023-03-14

我也有同样的工作。我正在使用logstash对elastic中的文档进行索引。

根本原因:

我已经探究了根本原因。默认情况下,elastic分配5个分片,并且一组父子孙辈的文档必须位于同一分片中。不幸的是,数据分散在碎片上。Elastic将只返回在同一个碎片中的记录。

解决方案:

要使父子孙辈正常工作,您需要将父子文档id作为父子文档中的路由值。

对于单级(父-子级),父级值是deafult路由值,该值工作正常。但对于三个级别,您需要为grand child中的每个文档配置路由。

正如我所提到的,路由值应该是grandparentid。

请使用logstash找到下面的示例:

>

  • 母公司

    "index" => "search"
    "document_type" => "parent"
    "document_id" => "%{appId}"
    

    子级:默认情况下工作,因为父级/路由与父级文档id相同。路由公式(shard\u num=hash(\u routing)%num\u primary\u shards)

    "index" => "search"
    "document_type" => "child"
    "document_id" => "%{lId}"
    "parent" => "%{appId}"
    

    孙子:注意路由是appId,它是盛大的父文档id

    "index" => "search"
    "document_type" => "grandchild"
    "document_id" => "%{lBId}"
    "parent" => "%{lId}"
    "routing" => "%{appId}"
    

    这将把所有文档索引到同一个分片,在这个用例中搜索工作正常。

  •  类似资料:
    • 问题内容: 我的操作: 父母:国家/地区,孩子:分支机构,孙子:员工 PUT / company {“ mappings”:{“ branch”:{“ _parent”:{“ type”:“ country”}}},“ employee”:{“ _parent”:{“ type”:“ branch”}}}}} 我想添加一个孙子雇员2,父母是分支: PUT / company / employee2

    • 问题内容: Book,User和Review说,我正在构建具有复杂模型的应用程序。 评论包含书籍和用户ID。为了能够搜索至少包含一个评论的“图书”,我已将“图书”设置为“评论”的父级,并且具有这样的路由。但是,我还需要找到撰写包含某些短语的评论的用户。 是否可以同时将书和用户作为评论的父级?有没有更好的方法来处理这种情况? 请注意,我无法更改数据建模的方式/不愿意这样做,因为数据已从持久性数据库传

    • 伪代码: 为什么大多数程序通常不允许这样做(我从未见过)? 程序不能识别出它何时进行了循环并停止执行任务吗? 对于实例: 假设这些对象是3d网格,我们想在x轴上转换对象A 2个单位。通常,父子关系会移动A的任何子级。所以它穿过子树,并用A翻译x轴上的每个子级2个单位。然后它到达树中的对象A,而不是移动它,为什么不让它检查身份,如果身份返回true,然后停止移动东西? 这只是软件开发人员的懒惰吗?

    • 问题内容: 当我运行以下脚本时,两个lambda都在同一文件junk.txt上运行os.startfile()。我希望每个Lambda都使用创建Lambda时设置的值“ f”。有没有办法让它按我的预期运行? 问题答案: 一种方法是执行此操作: 否则,在调用该函数时将进行查找,因此您将获得当前(循环后)的值。 我更喜欢的方式: 甚至(在python 2.5+中):

    • 使用ES(或Solr)建模productvariants让我大吃一惊 考虑(人为的例子): 不同的产品(如T恤) 每个产品都有一组属性(productid、名称、desc、品牌、颜色、知名度) 每个产品都有一组具有属性的productvariants(productvariantid(productid++大小的组合)、productid、大小、可用性、价格) 这似乎是product和Produc

    • 我有一个场景,需要在一种情况下加载所有子值,在另一种情况下加载一些特定的子值。我对这两种情况都使用一个bean,并使用命名查询编写查询。 现在在我的查询2中,我只需要加载字符串A,而不需要加载字符串B和字符串C。我试过使用 但得到以下错误 那么,关于如何继续这方面的任何建议。。