stored specify script_fields results query includes fields sorting elasticsearch aggregation

sorting - specify - query field elasticsearch



ElasticSearch agregación multinivel padre-hijo (2)

Tengo una estructura padre / hijo en 3 niveles. Digamos:

Empresa -> Empleado -> Disponibilidad

Como Disponibilidad (y también Empleado) se actualiza con frecuencia aquí, elijo usar la estructura padre / hijo contra anidada. Y la función de búsqueda funciona bien (todos los documentos en fragmentos correctos).

Ahora quiero ordenar esos resultados. Ordenarlos por metadatos de la compañía (primer nivel) es fácil. Pero necesito ordenar también por 3er nivel (disponibilidad).

Quiero una lista de empresas ordenadas por:

  • Distancia desde la ubicación dada ASC
  • Calificación DESC
  • Disponibilidad más pronto ASC

Por ejemplo:

La Compañía A está a 5 millas de distancia, tiene una calificación de 4 y pronto uno de sus empleados está disponible en 20 horas La Compañía B también está a 5 millas de distancia, también tiene una calificación de 4 pero pronto uno de sus empleados está disponible en 5 horas.

Por lo tanto, el resultado de clasificación debe ser B, A.

Me gustaría agregar un peso especial a cada uno de estos datos, así que comencé a escribir agregaciones que luego podría usar en mi script custom_score.

Resumen completo para crear índices, importar datos y buscar

Ahora, he logrado escribir una consulta que realmente devuelve el resultado, pero el depósito de agregación de disponibilidad está vacío. Sin embargo, también estoy obteniendo resultados demasiado estructurados, me gustaría aplanarlos.

Actualmente regreso:

ID de empresa -> ID de empleado -> primera disponibilidad

Me gustaría tener agregaciones como:

IDS de la empresa -> primera disponibilidad

De esta manera, puedo hacer mi script custom_score para calcular la puntuación y ordenarlos correctamente.

Pregunta más simplificada:
¿Cómo se puede clasificar / agregar por varios niveles (grand) hijos y posiblemente aplanar el resultado.



No necesita agregaciones para hacer esto:

Estos son los criterios de clasificación:

  1. Distancia ASC (empresa.ubicación)
  2. Calificación DESC (company.rating_value)
  3. Pronto disponibilidad futura ASC (company.employee.availability.start)

Si ignora el n. ° 3, puede ejecutar una consulta de empresa relativamente simple como esta:

GET /companies/company/_search { "query": { "match_all" : {} }, "sort": { "_script": { "params": { "lat": 51.5186, "lon": -0.1347 }, "lang": "groovy", "type": "number", "order": "asc", "script": "doc[''location''].distanceInMiles(lat,lon)" }, "rating_value": { "order": "desc" } } }

El n. ° 3 es complicado porque necesita alcanzar y encontrar la disponibilidad ( empresa> empleado> disponibilidad ) para cada compañía más cercana al momento de la solicitud y usar esa duración como un tercer criterio de clasificación.

Vamos a utilizar una consulta function_score en el nivel de nieto para tomar la diferencia horaria entre el tiempo de solicitud y cada disponibilidad en el hit _score . (Luego usaremos el _score como el tercer criterio de clasificación).

Para llegar a los nietos necesitamos usar una consulta has_child dentro de una consulta has_child .

Para cada empresa, queremos el Empleado más pronto disponible (y, por supuesto, su Disponibilidad más cercana). Elasticsearch 2.0 nos dará un "score_mode": "min" para casos como este, pero por ahora, ya que estamos limitados a "score_mode": "max" haremos que el nieto _score sea ​​el recíproco de la diferencia horaria .

"function_score": { "filter": { "range": { "start": { "gt": "2014-12-22T10:34:18+01:00" } } }, "functions": [ { "script_score": { "lang": "groovy", "params": { "requested": "2014-12-22T10:34:18+01:00", "millisPerHour": 3600000 }, "script": "1 / ((doc[''availability.start''].value - new DateTime(requested).getMillis()) / millisPerHour)" } } ] }

Por lo tanto, ahora la _score para cada nieto ( Disponibilidad ) será 1 / number-of-hours-until-available (para que podamos utilizar el tiempo recíproco máximo hasta que esté disponible por Empleado, y el Empleado recíproco máximo disponible por empresa) )

En conjunto, seguimos consultando a la empresa, pero usamos la disponibilidad empresa> empleado> para generar el _score para usar como criterio de clasificación n. ° 3 :

GET /companies/company/_search { "query": { "has_child" : { "type" : "employee", "score_mode" : "max", "query": { "has_child" : { "type" : "availability", "score_mode" : "max", "query": { "function_score": { "filter": { "range": { "start": { "gt": "2014-12-22T10:34:18+01:00" } } }, "functions": [ { "script_score": { "lang": "groovy", "params": { "requested": "2014-12-22T10:34:18+01:00", "millisPerHour": 3600000 }, "script": "1/((doc[''availability.start''].value - new DateTime(requested).getMillis()) / millisPerHour)" } } ] } } } } } }, "sort": { "_script": { "params": { "lat": 51.5186, "lon": -0.1347 }, "lang": "groovy", "type": "number", "order": "asc", "script": "doc[''location''].distanceInMiles(lat,lon)" }, "rating_value": { "order": "desc" }, "_score": { "order": "asc" } } }