Как искать только по последнему вставленному объекту (известному по полю даты) в массиве вложенных объектов в elasticsearch - PullRequest
1 голос
/ 25 мая 2020

У меня есть массив объектов в моем индексе elasticsearch, например:

{
  "group": "test_q",
  "artifact_type": "dashboard",
  "descriptions": [
    {
      "value": "original_description",
      "created_at": "2010-06-07T12:54:52Z",
      "created_by": "user_1"
    },
    {
      "value": "edited_description",
      "created_at": "2020-05-25T12:54:52Z",
      "created_by": "user_2"
    }
  ]
}

Каждый раз, когда описание обновляется, новый объект вставляется в массив описаний. Один из моих вариантов использования - всегда запрашивать самое последнее описание.

Моя идея заключалась в том, чтобы отсортировать массив по created_date в порядке убывания, выбрать первый и запросить его. Но как мне это сделать. Я относительно новичок в elasticsearch и не могу понять, может ли кто-нибудь помочь мне с образцом запроса.

Я использую elasti c search version 5.6

Заранее спасибо ?

Обновление: публикация сопоставлений полей, как указано в комментариях:

  "properties": {
    "descriptions": {
      "type": "nested",
      "properties": {
        "created_at": {
          "type": "date"
        },
        "created_by": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "value": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }

Обновление: единственный способ, о котором я могу думать прямо сейчас, - это добавить «последнее» логическое поле во вложенное объект. Но должен быть способ получше.

1 Ответ

0 голосов
/ 26 мая 2020

Это точно установлено , что тип nested

лучше всего подходит для данных, которые не меняются часто

, поэтому я бы рекомендую сделать ваш индекс основанным на описании (на верхнем уровне), а не на групповом.


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

GET your_index/_search
{
  "script_fields": {
    "latest_desc": {
      "script": {
        "source": """
           def descriptions = params._source.descriptions;
           def sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
           def latest_obj = null;
           def latest_millis = 0;
           for (def desc : descriptions) {
             def iteration_millis = sf.parse(desc.created_at).getTime();
             if (iteration_millis > latest_millis) {
               latest_millis = iteration_millis;
               latest_obj = desc;
             }
           }

           return latest_obj
        """
      }
    }
  }
}

Затем вы можете объединить это с глобальной вложенной сортировкой, которая поместит родительские объекты с самыми последними отметками времени наверх:

"query: {}, ...
"sort": [
    {
      "descriptions.created_at": {
        "order": "desc",
        "nested_path": "descriptions"
      }
    }
  ],
"script_fields": {} ...
...