ElasticSearch: найти несколько уникальных значений в массиве со сложными объектами - PullRequest
2 голосов
/ 16 апреля 2020

Предположим, что существует индекс с документами следующей структуры:

{
    "array": [
        {
            "field1": 1,
            "field2": 2
        },
        {
            "field1": 3,
            "field2": 2
        },
        {
            "field1": 3,
            "field2": 2
        },
        ...
    ]
}

Можно ли определить запрос, который возвращает документы, имеющие несколько уникальных значений для поля?

В приведенном выше примере запрос, выполняющий поиск по field2 , не будет возвращать документ, поскольку все имеют одинаковое значение, но при поиске по field1 вернет его, потому что он имеет значения 1 и 3.

Единственное, о чем я могу думать, - это сохранить уникальные значения в родительском объекте, а затем запросить его длину, но, как это кажется тривиальным, я надеюсь решить его, не меняя структуру на что-то вроде:

{
    "arrayField1Values" : [1, 3],
    "arrayField2Values" : [2]
    "array": [
        {
            "field1": 1,
            "field2": 2
        },
        {
            "field1": 3,
            "field2": 2
        },
        {
            "field1": 3,
            "field2": 2
        },
        ...
    ]
}

Спасибо всем, кто может помочь!

1 Ответ

1 голос
/ 16 апреля 2020

Я догадывался о go с типом данных nested, но потом я понял, что вы можете сделать простой отдельный подсчет значений массива полей 1 и 2, используя query scripts и top_hits:

PUT array

POST array/_doc
{
  "array": [
    {
      "field1": 1,
      "field2": 2
    },
    {
      "field1": 3,
      "field2": 2
    },
    {
      "field1": 3,
      "field2": 2
    }
  ]
}

GET array/_search
{
  "size": 0,
  "aggs": {
    "field1_is_unique": {
      "filter": {
        "script": {
          "script": {
            "source": "def uniques = doc['array.field1'].stream().distinct().sorted().collect(Collectors.toList()); return uniques.length > 1 ;",
            "lang": "painless"
          }
        }
      },
      "aggs": {
        "top_hits_field1": {
          "top_hits": {}
        }
      }
    },
    "field2_is_unique": {
      "filter": {
        "script": {
          "script": {
            "source": "def uniques = doc['array.field2'].stream().distinct().sorted().collect(Collectors.toList()); return uniques.length > 1 ;",
            "lang": "painless"
          }
        }
      },
      "aggs": {
        "top_hits_field2": {
          "top_hits": {}
        }
      }
    }
  }
}

, что позволяет получить отдельные агрегации для включенных уникальных значений field1 или field2> 1:

 "aggregations" : {
    "field1_is_unique" : {
      "doc_count" : 1,
      "top_hits_field1" : {
        "hits" : {
          "total" : {
            "value" : 1,
            "relation" : "eq"
          },
          "max_score" : 1.0,
          "hits" : [
            {
              "_index" : "array",
              "_type" : "_doc",
              "_id" : "WbJhgnEBVBaNYdXKNktL",
              "_score" : 1.0,
              "_source" : {
                "array" : [
                  {
                    "field1" : 1,
                    "field2" : 2
                  },
                  {
                    "field1" : 3,
                    "field2" : 2
                  },
                  {
                    "field1" : 3,
                    "field2" : 2
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "field2_is_unique" : {
      "doc_count" : 0,
      "top_hits_field2" : {
        "hits" : {
          "total" : {
            "value" : 0,
            "relation" : "eq"
          },
          "max_score" : null,
          "hits" : [ ]
        }
      }
    }
  }

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...