Elasticsearch更深层次的亲子关系(孙子)

era*_*ran 18 elasticsearch

我需要索引3个级别(或更多)的child-parent.例如,级别可能是作者,书籍和该书中的字符.

但是,当索引超过两个级别时,has_child和has_parent查询和过滤器存在问题.如果我有5个分片,当在最低级别(字符)上运行"has_parent"查询或在第二级(书籍)上运行has_child查询时,我得到大约五分之一的结果.

我的猜测是,一本书通过它的父ID被索引到一个碎片,因此它将与他的父(作者)一起驻留,但是一个角色根据书籍ID的散列被索引到一个碎片,这不一定符合本书编入索引的实际分片.

因此,这意味着同一作者的所有书籍都不一定存在于同一个碎片中(真正破坏整个孩子 - 父母的优势).

难道我做错了什么?我如何解决这个问题,因为我真的需要复杂的查询,例如"作者用女性角色写书".

我疯狂地表达了这个问题,请访问:https: //gist.github.com/eranid/5299628

底线是,如果我有一个映射:

"author" : {          
      "properties" : {
    "name" : {
      "type" : "string"
    }
      }
    },
"book" : {        
      "_parent" : {
    "type" : "author"
      },
      "properties" : {
    "title" : {
      "type" : "string"
    }
      }
    },

"character" : {       
      "_parent" : {
    "type" : "book"
      },
      "properties" : {
    "name" : {
      "type" : "string"
    }
      }
    }
Run Code Online (Sandbox Code Playgroud)

和5个分片索引,我不能用"has_child"和"has_parent"查询

查询:

curl -XPOST 'http://localhost:9200/index1/character/_search?pretty=true' -d '{
  "query": {
    "bool": {
      "must": [
        {
          "has_parent": {
            "parent_type": "book",
            "query": {
              "match_all": {}
            }
          }
        }
      ]
    }
  }
}'
Run Code Online (Sandbox Code Playgroud)

只返回五分之一(大约)的字符.

imo*_*tov 25

您是正确的,父/子关系只能在给定父级的所有子级与父级位于同一分片中时才能工作.Elasticsearch通过使用父ID作为路由值来实现此目的.它在一个层面上运行良好.然而,它在第二和连续的水平上打破.如果您有父/子/孙子关系,父母会根据他们的ID进行路由,则会根据父ID(工作)路由子项,但是孙子会根据子ID进行路由,最终会出现错误的分片.为了在示例中演示它,我们假设我们正在索引3个文档:

curl -XPUT localhost:9200/test-idx/author/Douglas-Adams -d '{...}'
curl -XPUT localhost:9200/test-idx/book/Mostly-Harmless?parent=Douglas-Adams -d '{...}'
curl -XPUT localhost:9200/test-idx/character/Arthur-Dent?parent=Mostly-Harmless -d '{...}'
Run Code Online (Sandbox Code Playgroud)

Elasticsearch使用值Douglas-Adams来计算文档的路由Douglas-Adams- 这并不奇怪.对于该文档Mostly-Harmless,Elasticsearch认为它具有父级Douglas-Adams,因此它再次Douglas-Adams用于计算路由并且一切都很好 - 相同的路由值意味着相同的分片.但是对于文档Arthur-DentElasticsearch看到它有父类Mostly-Harmless,所以它使用值Mostly-Harmless作为路由,结果文档Arthur-Dent以错误的分片结束.

对此的解决方案是明确指定孙子的路由值等于祖父母的id:

curl -XPUT localhost:9200/test-idx/author/Douglas-Adams -d '{...}'
curl -XPUT localhost:9200/test-idx/book/Mostly-Harmless?parent=Douglas-Adams -d '{...}'
curl -XPUT localhost:9200/test-idx/character/Arthur-Dent?parent=Mostly-Harmless&routing=Douglas-Adams -d '{...}'
Run Code Online (Sandbox Code Playgroud)

  • 在URL上使用路由参数.请参阅此处的路由部分 - http://www.elasticsearch.org/guide/reference/api/index_/ (4认同)
  • 我想知道您是否可以阐明此问题的发生方式-如果子级与父级路由到相同的分片,孙子级与子级路由到相同的分片,那么“亲戚”不应该全部以同一分号结尾吗? (2认同)