2017-02-07 8 views
0

Я вижу то, что кажется аберрантным поведением в результатах inner_hits в вложенных логических запросах.Empty inner_hits в составном Elasticearch filter

Тестовые данные (сокращенно для краткости):

# MAPPING 
PUT unit_testing 
{ 
    "mappings": { 
     "document": { 
      "properties": { 
       "display_name": {"type": "text"}, 
       "metadata": { 
        "properties": { 
         "NAME": {"type": "text"} 
        } 
       } 
      } 
     }, 
     "paragraph": { 
      "_parent": {"type": "document"}, 
      "_routing": {"required": true}, 
      "properties": { 
       "checksum": {"type": "text"}, 
       "sentences": { 
        "type": "nested", 
        "properties": { 
         "text": {"type": "text"} 
        } 
       } 
      } 
     } 
    } 
} 

# DOCUMENT X 2 (d0, d1) 
PUT unit_testing/document/doc_id_d0 
{ 
    "display_name": "Test Document d0", 
    "paragraphs": [ 
     "para_id_d0p0", 
     "para_id_d0p1" 
    ], 
    "metadata": {"NAME": "Test Document d0 Metadata"} 
} 

# PARAGRAPH X 2 (d0p0, d1p0) 
PUT unit_testing/paragraph/para_id_d0p0?parent=doc_id_d0 
{ 
    "checksum": "para_checksum_d0p0", 
    "sentences": [ 
     {"text": "Test sentence d0p0s0"}, 
     {"text": "Test sentence d0p0s1 ODD"}, 
     {"text": "Test sentence d0p0s2 EVEN"}, 
     {"text": "Test sentence d0p0s3 ODD"}, 
     {"text": "Test sentence d0p0s4 EVEN"} 
    ] 
} 

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

GET unit_testing/paragraph/_search 
{ 
    "_source": "false", 
    "query": { 
     "bool": { 
      "must": [ 
       { 
        "has_parent": { 
         "query": { 
          "match_phrase": { 
           "metadata.NAME": "Test Document d0 Metadata" 
          } 
         }, 
         "type": "document" 
        } 
       }, 
       { 
        "nested": { 
         "inner_hits": {}, 
         "path": "sentences", 
         "query": { 
          "match": { 
           "sentences.text": "d0p0s0" 
          } 
         } 
        } 
       } 
      ] 
     } 
    } 
} 

Это дает inner_hits объект, содержащий одно предложение, которое соответствовало предикат (некоторые поля удалены для ясности):

{ 
    "hits": { 
    "hits": [ 
     { 
     "_source": {}, 
     "inner_hits": { 
      "sentences": { 
      "hits": { 
       "hits": [ 
       { 
        "_source": { 
        "text": "Test sentence d0p0s0" 
        } 
       } 
       ] 
      } 
      } 
     } 
     } 
    ] 
    } 
} 

Следующий запрос является попыткой встроить выше запрос в родителя «должен» пункт, чтобы создать логическое ИЛИ между первоначальным запросом и дополнительный запрос, который соответствует одно предложение:

GET unit_testing/paragraph/_search 
{ 
    "_source": "false", 
    "query": { 
     "bool": { 
      "should": [ 
       { 
        "bool": { 
         "must": [ 
          { 
           "has_parent": { 
            "query": { 
             "match_phrase": { 
              "metadata.NAME": "Test Document d0 Metadata" 
             } 
            }, 
            "type": "document" 
           } 
          }, 
          { 
           "nested": { 
            "inner_hits": {}, 
            "path": "sentences", 
            "query": { 
             "match": { 
              "sentences.text": "d0p0s0" 
             } 
            } 
           } 
          } 
         ] 
        } 
       }, 
       { 
        "nested": { 
         "inner_hits": {}, 
         "path": "sentences", 
         "query": { 
          "match": { 
           "sentences.text": "d1p0s0" 
          } 
         } 
        } 
       } 
      ] 
     } 
    } 
} 

В то время как «d1» запрос выводит результат можно был бы ожидать, с inner_hits объекта, содержащего соответствующее предложение, оригинальный «d0» запрос в настоящее время приводит к пустому inner_hits объект:

{ 
    "hits": { 
    "hits": [ 
     { 
     "_source": {}, 
     "inner_hits": { 
      "sentences": { 
      "hits": { 
       "total": 0, 
       "hits": [] 
      } 
      } 
     } 
     }, 
     { 
     "_source": {}, 
     "inner_hits": { 
      "sentences": { 
      "hits": { 
       "hits": [ 
       { 
        "_source": { 
        "text": "Test sentence d1p0s0" 
        } 
       } 
       ] 
      } 
      } 
     } 
     } 
    ] 
    } 
} 

Хотя я использую библиотеку elasticsearch_dsl Python для строить и комбинировать эти запросы, и я - что-то вроде новичка с уважением t o Запрос DSL, формат запроса выглядит солидным для меня.

Что мне не хватает?

ответ

1

Я думаю, что отсутствует параметр name для inner_hits - у вас есть два предложения inner_hits в двух разных запросах, которые будут иметь одноименное имя. Попробуйте указать параметр inner_hits a name (0).

0 - https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-inner-hits.html#_options

+0

Отличный улов! Вот и все. Большое спасибо Honza. – nate