Агрегации массива во вложенном запросе

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

Часть моего документа для примера пользователя выглядит следующим образом:

{
    // ... other fields
    "colors" : [
        {
            "id" : 1,
            "name" : "Green"
        },
        {
            "id" : 7,
            "name" : "Blue"
        }
    ]
}

Это мой запрос для получения общих цветов с другим пользователем, который имеет красный, оранжевый и зеленый цвета:

{
  "query": {
    "nested": {
      "path": "colors",
      "scoreMode": "sum",
      "query": {
        "function_score": {
          "filter": {
            "terms": {
              "colors.name": [
                "Red","Orange","Green"
              ]
            }
          },
          "functions": [
            // Functions here for custom scoring
          ]
        }
      }
    }
  }
}

Как я могу объединить пользователей с общими цветами?


person mohit1234    schedule 16.01.2016    source источник
comment
Если я правильно понимаю ваш вопрос и использую приведенный вами пример, вам нужен список пользователей для каждого из следующих цветов: красный, оранжевый и зеленый?   -  person bittusarkar    schedule 16.01.2016
comment
Нет. Я объясню еще раз. Допустим, у меня есть пользователь А, и у него есть красный, оранжевый и зеленый цвета. Теперь я ищу всех пользователей, у которых есть хотя бы один из этих цветов. Затем я хочу объединить пользователей с общими цветами с пользователем А. Итак, если у пользователя X были цвета синий, зеленый и желтый, а у пользователя Y были цвета синий, красный и оранжевый, то я хочу вернуть пользователя X - [Зеленый] и Пользователь Y - [Красный, Оранжевый]. Имеет ли это смысл? В основном я пытаюсь получить общие цвета между текущим пользователем и всеми пользователями в моей базе данных.   -  person mohit1234    schedule 16.01.2016
comment
Хорошо, теперь я понимаю ваш вопрос.   -  person bittusarkar    schedule 16.01.2016
comment
Могу ли я предположить, что в вашем документе есть поле с именем user_id вместе с цветами поля?   -  person bittusarkar    schedule 16.01.2016
comment
Да, это нормально. У него есть поле user_id.   -  person mohit1234    schedule 16.01.2016


Ответы (2)


Вы должны использовать nested aggregations для достижения этого. См. запрос ниже:

POST <index>/<type>/_search
{
   "query": {
      "nested": {
         "path": "colors",
         "query": {
            "terms": {
               "colors.name": [
                  "Red",
                  "Orange",
                  "Green"
               ]
            }
         }
      }
   },
   "aggs": {
      "users_with_common_colors": {
         "terms": {
            "field": "user_id",
            "size": 0,
            "order": {
                "color_distribution>common": "desc"  <-- This will sort the users in descending order of number of common colors
            }
         },
         "aggs": {
            "color_distribution": {
               "nested": {
                  "path": "colors"
               },
               "aggs": {
                  "common": {
                     "filter": {
                        "terms": {
                           "colors.name": [
                              "Red",
                              "Orange",
                              "Green"
                           ]
                        }
                     },
                     "aggs": {
                        "colors": {
                           "terms": {
                              "field": "colors.name",
                              "size": 0
                           }
                        }
                     }
                  }
               }
            }
         }
      }
   }
}
person bittusarkar    schedule 16.01.2016
comment
Спасибо, это именно то, что мне было нужно! Мне было интересно, можно ли сортировать агрегации по количеству общих цветов? Я попытался добавить заказ, но столкнулся с ошибками, так как вложенный - это ведро с несколькими значениями. - person mohit1234; 16.01.2016
comment
Я пытался это сделать, но получил следующую ошибку: "Invalid terms aggregation order path [color_distribution>common]. Terms buckets can only be sorted on a sub-aggregator path that is built out of zero or more single-bucket aggregations within the path and a final single-bucket or a metrics aggregation at the path end. Sub-path [color_distribution] points to non single-bucket aggregation" - person mohit1234; 16.01.2016
comment
nvm, я разобрался как это сделать с помощью top_hits. Спасибо за вашу помощь! - person mohit1234; 16.01.2016
comment
@bittusarkar - Как я могу сделать это для многозначного ведра? Отдельный вопрос - stackoverflow.com/questions/43451667/ - person Jay Shah; 17.04.2017

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

Это запрос

{
  "size": 0,
  "query": {
    "nested": {
      "path": "colors",
      "query": {
        "terms": {
          "colors.color": [
            "green",
            "red"
          ]
        }
      }
    }
  },
  "aggs": {
    "user": {
      "terms": {            <----get users with unique name or user_id
        "field": "name",
        "size": 10
      },
      "aggs": {
        "nested_color_path": {  <---go inside nested documents
          "nested": {
            "path": "colors"
          },
          "aggs": {
            "match_color": {
              "filter": {         <--- use the filter to match for colors
                "terms": {
                  "colors.color": [
                    "green",
                    "red"
                  ]
                }
              },
              "aggs": {
                "get_match_color": {  <--- use this to get matched color
                  "top_hits": {
                    "size": 10,
                     "_source": {
                       "include": "name"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
person ChintanShah25    schedule 16.01.2016
comment
Как я могу сделать это для многозначного ведра? Отдельный вопрос - stackoverflow.com/questions/43451667/ - person Jay Shah; 17.04.2017