【问题标题】:ElasticSearch: Grandchild/child/parent relations not working properlyElasticSearch:孙子/子/父关系无法正常工作
【发布时间】:2017-10-06 09:52:37
【问题描述】:

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

这是我的地图:

PUT /test_index

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

索引 parentDoc:

PUT /test_index/parentDoc/1

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

PUT /test_index/parentDoc/2

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

索引 childDoc:

PUT /test_index/childDoc/10?parent=1

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

PUT /test_index/childDoc/101?parent=1

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

PUT /test_index/childDoc/20?parent=2

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

索引 grandChildDoc:

PUT /test_index/grandChildDoc/100?parent=10

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

PUT /test_index/grandChildDoc/200?parent=10

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

PUT /test_index/grandChildDoc/300?parent=20

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

现在,当我要求 elastic-search 向我显示那些具有 childDocparentDoc 时,它会返回: 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 向我展示那些具有 grandChildDocchildDoc 时,它会返回: POST /test_index/childDoc/_search

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

结果:(在这里,您会注意到缺少一些匹配项。例如,ID 为 10childDoc 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]

【问题讨论】:

    标签: elasticsearch indexing elasticsearch-5


    【解决方案1】:

    我也有同样的工作。我正在使用 logstash 来索引弹性文档。

    根本原因:

    我已经探索了根本原因。默认情况下,elastic 分配 5 个分片,并且一组父-子-孙的文档必须位于同一个分片中。不幸的是,数据分布在各个分片中。 Elastic 将仅返回位于同一分片中的那些记录。

    解决方案:

    要使父子孙子工作,您需要将祖父文档ID作为孙子文档中的路由值。

    对于单级(父子),父值是默认路由值,可以正常工作。但是对于三层,您需要为孙子中的每个文档配置路由。

    正如我所提到的,路由值应该是祖父 ID。

    请使用 logstash 查找以下示例:

    1. 父母

      "index" => "search"
      "document_type" => "parent"
      "document_id" => "%{appId}"
      
    2. 子:默认情况下工作,因为父/路由与父文档 ID 相同。路由公式(shard_num = hash(_routing) % num_primary_shards)

      "index" => "search"
      "document_type" => "child"
      "document_id" => "%{lId}"
      "parent" => "%{appId}"
      
    3. 孙子:注意路由是appId,它是祖父文档ID

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-13
      • 2012-08-27
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      相关资源
      最近更新 更多