Как создать HashMap с настраиваемым объектом в качестве ключа? - PullRequest
1 голос
/ 18 июня 2020

В Elasticsearch у меня есть объект, содержащий массив объектов. Каждый объект в массиве имеет поля type, id, updateTime, value.

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

Я хотел бы использовать сценарий P безболезненно, чтобы обновить их, но сохранить их различными, так как некоторые из них могут перекрываться . Проблема в том, что мне нужно использовать как type, так и id, чтобы сохранить их уникальность. До сих пор я делал это с помощью подхода грубой силы, вложенного for l oop и сравнения элементов обоих массивов, но я не очень этому рад.

Одна из идей - взять массив из источника создать временную HashMap для быстрого поиска, обработки ввода и последующего сохранения всех объектов обратно в источник.

Могу ли я создать HashMap с настраиваемым объектом (класс с type и id) в качестве ключа? Если да, то как это сделать? Я не могу добавить определение класса в сценарий.

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

{
  "properties": {
    "arrayOfObjects": {
      "properties": {
        "typ": {
          "enabled": false
        },
        "id": {
          "enabled": false
        },
        "value": {
          "enabled": false
        },
        "updated": {
          "enabled": false
        }
      }
    }
  }
}

Пример do c.

{
  "arrayOfObjects": [
    {
      "typ": "a",
      "id": "1",
      "updated": "2020-01-02T10:10:10Z",
      "value": "yes"
    },
    {
      "typ": "a",
      "id": "2",
      "updated": "2020-01-02T11:11:11Z",
      "value": "no"
    },
    {
      "typ": "b",
      "id": "1",
      "updated": "2020-01-02T11:11:11Z"
    }
  ]
}

И, наконец, часть скрипта в его нынешнем виде. Скрипт выполняет и другие функции, поэтому я вырезал их для краткости.

if (ctx._source.arrayOfObjects == null) {
    ctx._source.arrayOfObjects = new ArrayList();
}
for (obj in params.inputObjects) {
    def found = false;
    for (existingObj in ctx._source.arrayOfObjects) {
        if (obj.typ == existingObj.typ && obj.id == existingObj.id && isAfter(obj.updated, existingObj.updated)) {
            existingObj.updated = obj.updated;
            existingObj.value = obj.value;
            found = true;
            break;
        }
    }
    if (!found) {
        ctx._source.arrayOfObjects.add([
            "typ": obj.typ,
            "id": obj.id,
            "value": params.inputValue,
            "updated": obj.updated
        ]);
    }
}

1 Ответ

1 голос
/ 19 июня 2020

Технически в вашем подходе нет ничего неоптимального.

A HashMap потенциально может сэкономить время, но, поскольку вы пишете сценарий, вы уже привязаны к его врожденной неэффективности ... Кстати, вот как вы инициализируете и работаете с HashMaps.

Другой подход может заключаться в переосмыслении вашей структуры данных - вместо массивов объектов используйте объекты с ключами или аналогичные. Массивы объектов не подходят для частого обновления.

Наконец, совет: вы сказали, что эти поля используются только для хранения некоторого промежуточного состояния. Если бы это было не так (или не будет в будущем), я бы рекомендовал использовать массивы nested, чтобы разрешить запросы независимо от других объектов в массиве .

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