2014-01-22 2 views
2

У меня есть два типа документа, в отношениях родитель-ребенок:Проблемы с has_parent запрос, содержащий сценарий function_score

"myParent" : { 
    "properties" : { 
    "weight" : { 
     "type" : "double" 
    } 
    } 
} 

"myChild" : { 
    "_parent" : { 
    "type" : "myParent" 
    }, 
    "_routing" : { 
    "required" : true 
    } 
} 

Поле weight будет использоваться для настраиваемого скоринга/сортировкой. Этот запрос непосредственно против родительских документов работает по назначению:

{ 
    "query" : { 
    "function_score" : { 
     "script_score" : { 
     "script" : "_score * doc['weight'].value" 
     }     
    }                  
    }  
} 

Однако при попытке сделать подобный счет для дочерних документов с has_parent запросом, я получаю сообщение об ошибке:

{ 
    "query" : { 
    "has_parent" : { 
     "query" : { 
     "function_score" : {              
      "script_score" : { 
      "script" : "_score * doc['weight'].value" 
      } 
     } 
     }, 
     "parent_type" : "myParent", 
     "score_type" : "score" 
    } 
    } 
} 

Ошибкой является :

QueryPhaseExecutionException[[myIndex][3]: query[filtered(ParentQuery[myParent](filtered(function score (ConstantScore(:),function=script[_score * doc['weight'].value], params [null]))->cache(_type:myParent)))->cache(_type:myChild)],from[0],size[10]: Query Failed [failed to execute context rewrite]]; nested: ElasticSearchIllegalArgumentException[No field found for [weight] in mapping with types [myChild]];

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

Если я не использую score для score_type, ошибка не возникает, хотя результаты оцениваются тогда 1.0, как задокументировано.

Что мне здесь не хватает? Как я могу запросить эти дочерние документы с пользовательским подсчетом на основе родительского поля?

+0

щедрот? :) – DrTech

+0

@DrTech Терпение, Яго, терпение;) –

+0

: D/me терпеливо ждет – DrTech

ответ

6

Это я бы сказал, это ошибка: он использует myChild отображение как контекст по умолчанию, даже если вы находитесь в запросе has_parent. Но я не уверен, насколько легко исправить ошибку. должным образом.

Однако, вы можете работать вокруг него, в том числе имени type в полном имени поля:

curl -XGET "http://localhost:9200/t/myChild/_search" -d' 
{ 
    "query": { 
    "has_parent": { 
     "query": { 
     "function_score": { 
      "script_score": { 
      "script": "_score * doc[\"myParent.weight\"].value" 
      } 
     } 
     }, 
     "parent_type": "myParent", 
     "score_type": "score" 
    } 
    } 
}' 

Я открыл вопрос, чтобы увидеть, если мы можем получить это фиксированное #4914

+0

Спасибо, что сделал трюк! Я предполагаю, что нет никакой дополнительной стоимости для ссылки на родителя из детского контекста сценария, так как они всегда будут в одном осколке? –

+0

Правильно - без дополнительной оплаты. – DrTech

+0

Странно, что Martijn v Groningen связан с [gist] (https://gist.github.com/martijnvg/8639841) из раздела [Тема обсуждения ES] (https://groups.google.com/forum/# ! msg/elasticsearch/w7zgncPYMVY/K3qRlpd7TQ0J), которые не могут воспроизвести проблему. Мне было трудно понять, в чем разница. В любом случае, спасибо еще раз. –

2

Я думаю, проблема в том, что вы пытаетесь забить child документов на основе поля в документе parent и что оценка функции должна быть наоборот.

Чтобы решить эту проблему, моя идея состояла в том, чтобы сохранить отношение родителя/ребенка и счет с дочерними документами. Затем вы будете фильтровать дочерние документы и оценивать их в соответствии с weight в дочернем документе.

Пример:

"myParent" : { 
    "properties" : { 
     "name" : { 
      "type" : "string" 
     } 
    } 
} 

"myChild" : { 
    "_parent" : { 
     "type" : "myParent" 
    }, 
    "_routing" : { 
     "required" : true 
    }, 
    "properties": { 
     "weight" : { 
      "type" : "double" 
     } 
    } 
} 

Теперь вы можете использовать has_parent фильтр, чтобы выбрать все child документов, которые имеют определенную parent, а затем оценку их помощь function score:

{ 
    "query": { 
     "filtered": { 
      "query": { 
       "function_score" : { 
        "script_score" : { 
         "script" : "_score * doc['weight'].value" 
        } 
       } 
      }, 
      "filter": { 
       "has_parent": { 
        "parent_type": "myParent", 
        "query": { 
         "term": { 
          "name": "something" 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Так что если parent документов были сообщения в блоге и child, вы можете фильтровать все сообщения и оценивать комментарии на основе weight. Я сомневаюсь, что забил childs на основе parents возможно, хотя я могу ошибаться :)

Отказ от ответственности: первое сообщение стека переполнения ...

+0

«вы пытаетесь забить« детские »документы на основе поля в документе« parent ». Вы утверждаете, что дизайн неправильный, или объяснить ошибку? Ошибка не имеет для меня смысла, потому что 'script_score' находится в запросе' has_parent', поэтому я ожидаю, что он будет работать с 'родительскими 'документами. –

+0

Запрос 'has_parent' возвращает документы' child', которые имеют определенный родительский элемент. Таким образом, ошибка 'No field, найденная для [weight] при сопоставлении с типами [myChild]', в основном говорит о том, что функция 'script_score' пытается получить доступ к полю' weight', которое присутствует только в 'myParent'. Так что да, вам нужно изменить представление. – truemped

+0

Как я уже сказал, 'script_score' является * внутри *' has_parent', поэтому я бы ожидал, что 'doc' будет ссылаться на myParent в скрипте. –

Смежные вопросы