Подтвердить что ты не робот

Elasticsearch более глубокий уровень Родительские отношения (внук)

Мне нужно индексировать 3 уровня (или более) дочернего родителя. Например, уровни могут быть автором, книгой и персонажами из этой книги.

Однако при индексировании более двух уровней возникает проблема с has_child и has_parent запросами и фильтрами. Если у меня есть 5 осколков, я получаю около одной пятой результатов при запуске запроса "has_parent" на самом низком уровне (символы) или запрос has_child на втором уровне (книги).

Моя догадка заключается в том, что книга индексируется осколком по его родительскому идентификатору и поэтому будет находиться вместе со своим родителем (автором), но персонаж индексируется на осколок, основанный на хеше идентификатора книги, что не обязательно соответствует фактическому осколку, на который была проиндексирована книга.

Итак, это означает, что все персонажи книг того же автора не обязательно находятся в одном и том же осколке (например, на самом деле вредит всему преимуществу ребенка-родителя).

Я что-то делаю неправильно? Как я могу это решить, так как мне действительно нужны сложные запросы, такие как "то, что авторы писали с женскими персонажами".

Я сумасшедший, показывающий проблему, на: 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"
    }
      }
    }

и индекс 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": {}
            }
          }
        }
      ]
    }
  }
}'

возвращает только пятую (приблизительно) из символов.

4b9b3361

Ответ 1

Вы правы, отношения между родителями и дочерними могут работать только тогда, когда все дочерние элементы данного родителя находятся в том же осколке, что и родительский. Elasticsearch достигает этого, используя родительский идентификатор в качестве значения маршрутизации. Он отлично работает на одном уровне. Тем не менее, он ломается на втором и последовательном уровнях. Когда у вас есть отношения родителя/ребенка/внука, родители маршрутизируются на основе своего идентификатора, дети маршрутизируются на основе родительских идентификаторов (работ), но затем внуки маршрутизируются на основе идентификаторов детей, и они попадают в неправильные осколки. Чтобы продемонстрировать это на примере, предположим, что мы индексируем 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 '{...}'

Elasticsearch использует значение Douglas-Adams для расчета маршрутизации для документа Douglas-Adams - здесь не удивительно. Для документа Mostly-Harmless Elasticsearch видит, что у него есть родительский Douglas-Adams, поэтому он использует снова Douglas-Adams для вычисления маршрутизации, и все хорошо - то же значение маршрутизации означает тот же осколок. Но для документа Arthur-Dent Elasticsearch видит, что он имеет родительский 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 '{...}'

Ответ 2

Для дедушки, вам нужно получить _id как _routing. Для документов отца просто используйте _parent (grandpa._id) как _routing. Для дочерних документов просто используйте grandpa._id как _routing.