Запрос has_parent

Запрос has_parent возвращает дочерние документы, родительские документы которых соответствуют определенному запросу.

Запрос has_parent возвращает дочерние документы, родительские документы которых соответствуют определенному запросу. Вы можете установить родительско-дочерние отношения между документами в одном индексе, используя тип поля join.

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

Пример

Перед тем как вы сможете выполнить запрос has_parent, ваш индекс должен содержать поле join для установления родительско-дочерних отношений. Запрос на отображение индекса использует следующий формат:

PUT /example_index
{
  "mappings": {
    "properties": {
      "relationship_field": {
        "type": "join",
        "relations": {
          "parent_doc": "child_doc"
        }
      }
    }
  }
}

Для этого примера сначала настройте индекс, который содержит документы, представляющие продукты и их бренды, как описано в примере запроса has_child.

Чтобы найти дочерний документ родителя, используйте запрос has_parent. Следующий запрос возвращает дочерние документы (продукты), произведенные брендом, соответствующим запросу “economy”:

GET testindex1/_search
{
  "query" : {
    "has_parent": {
      "parent_type":"brand",
      "query": {
        "match" : {
          "name": "economy"
        }
      }
    }
  }
}

Ответ возвращает все продукты, произведенные брендом:

{
  "took": 11,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "testindex1",
        "_id": "4",
        "_score": 1,
        "_routing": "2",
        "_source": {
          "name": "Electronic watch",
          "sales_count": 300,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        }
      },
      {
        "_index": "testindex1",
        "_id": "5",
        "_score": 1,
        "_routing": "2",
        "_source": {
          "name": "Digital watch",
          "sales_count": 100,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        }
      }
    ]
  }
}

Извлечение внутренних результатов (inner hits)

Чтобы вернуть родительские документы, которые соответствуют запросу, укажите параметр inner_hits:

GET testindex1/_search
{
  "query" : {
    "has_parent": {
      "parent_type":"brand",
      "query": {
        "match" : {
          "name": "economy"
        }
      },
      "inner_hits": {}
    }
  }
}

Ответ содержит родительские документы в поле inner_hits:

{
  "took": 11,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "testindex1",
        "_id": "4",
        "_score": 1,
        "_routing": "2",
        "_source": {
          "name": "Electronic watch",
          "sales_count": 300,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        },
        "inner_hits": {
          "brand": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 1.3862942,
              "hits": [
                {
                  "_index": "testindex1",
                  "_id": "2",
                  "_score": 1.3862942,
                  "_source": {
                    "name": "Economy brand",
                    "product_to_brand": "brand"
                  }
                }
              ]
            }
          }
        }
      },
      {
        "_index": "testindex1",
        "_id": "5",
        "_score": 1,
        "_routing": "2",
        "_source": {
          "name": "Digital watch",
          "sales_count": 100,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        },
        "inner_hits": {
          "brand": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 1.3862942,
              "hits": [
                {
                  "_index": "testindex1",
                  "_id": "2",
                  "_score": 1.3862942,
                  "_source": {
                    "name": "Economy brand",
                    "product_to_brand": "brand"
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

Для получения дополнительной информации о извлечении внутренних результатов, смотрите раздел “Внутренние результаты” (Inner hits).

Параметры

Следующая таблица перечисляет все параметры верхнего уровня, поддерживаемые запросами has_parent.

Параметр Обязательный/Необязательный Описание
parent_type Обязательный Указывает имя родительской связи, как определено в отображении поля join.
query Обязательный Запрос, который будет выполнен на родительских документах. Если родительский документ соответствует запросу, возвращается дочерний документ.
ignore_unmapped Необязательный Указывает, следует ли игнорировать неотображаемые поля типа parent_type и не возвращать документы вместо того, чтобы вызывать ошибку. Этот параметр можно указать при запросе нескольких индексов, некоторые из которых могут не содержать поле parent_type. По умолчанию false.
score Необязательный Указывает, учитывается ли оценка релевантности соответствующего родительского документа в дочерних документах. Если false, то оценка релевантности родительского документа игнорируется, и каждому дочернему документу присваивается оценка релевантности, равная коэффициенту увеличения запроса, который по умолчанию равен 1. Если true, то оценка релевантности соответствующего родительского документа агрегируется в оценки релевантности его дочерних документов. По умолчанию false.
inner_hits Необязательный Если указан, возвращает внутренние результаты (родительские документы), которые соответствуют запросу.

Ограничения сортировки

Запрос has_parent не поддерживает сортировку результатов с использованием стандартных опций сортировки. Если вам необходимо отсортировать дочерние документы по полям их родительских документов, вы можете использовать запрос function_score и сортировать по оценке дочернего документа.

Для предыдущего примера сначала добавьте поле customer_satisfaction, по которому вы будете сортировать дочерние документы, принадлежащие родительским (брендовым) документам:

PUT testindex1/_doc/1
{
  "name": "Luxury watch brand",
  "product_to_brand" : "brand",
  "customer_satisfaction": 4.5
}

PUT testindex1/_doc/2
{
  "name": "Economy watch brand",
  "product_to_brand" : "brand",
  "customer_satisfaction": 3.9
}

Теперь вы можете сортировать дочерние документы (продукты) на основе поля customer_satisfaction их родительских брендов. Этот запрос умножает оценку на поле customer_satisfaction родительских документов:

GET testindex1/_search
{
  "query": {
    "has_parent": {
      "parent_type": "brand",
      "score": true,
      "query": {
        "function_score": {
          "script_score": {
            "script": "_score * doc['customer_satisfaction'].value"
          }
        }
      }
    }
  }
}

Ответ содержит продукты, отсортированные по наивысшему значению customer_satisfaction родительских документов:

{
  "took": 11,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 4.5,
    "hits": [
      {
        "_index": "testindex1",
        "_id": "3",
        "_score": 4.5,
        "_routing": "1",
        "_source": {
          "name": "Mechanical watch",
          "sales_count": 150,
          "product_to_brand": {
            "name": "product",
            "parent": "1"
          }
        }
      },
      {
        "_index": "testindex1",
        "_id": "4",
        "_score": 3.9,
        "_routing": "2",
        "_source": {
          "name": "Electronic watch",
          "sales_count": 300,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        }
      },
      {
        "_index": "testindex1",
        "_id": "5",
        "_score": 3.9,
        "_routing": "2",
        "_source": {
          "name": "Digital watch",
          "sales_count": 100,
          "product_to_brand": {
            "name": "product",
            "parent": "2"
          }
        }
      }
    ]
  }
}