Сортировка Elasticsearch по настраиваемому полю created_at

У меня есть поле created_at в моей базе данных Elastic Search, и я пытаюсь извлечь данные и отсортировать их по этому полю. Поле было сохранено со свойством сопоставления с форматом даты с ключом fielddata, установленным на true, но я все равно получаю сообщение об ошибке:

Текстовые поля не оптимизированы для операций, требующих данных поля для каждого документа, таких как агрегирование и сортировка, поэтому эти операции по умолчанию отключены. Вместо этого используйте поле ключевого слова. В качестве альтернативы установите fielddata = true для [created_at], чтобы загрузить данные поля путем отмены инвертирования инвертированного индекса. Обратите внимание, что для этого может потребоваться значительный объем памяти.

Одно из предложений состоит в том, что я могу добавить слово keyword в свое поле для поиска, но это, кажется, говорит мне, что:

created_at не определен

Я использую Javascript, и я знаю, что вы не можете просто добавить символ (точка), поэтому я завернул его, но он все еще не работает. elastic.find - это просто функция, которую я написал для извлечения данных, если я удалю массив sort, она сработает.

const results = await elastic.find('my table', {
  query: {
    range: {
      created_at: {
        gte: moment(from).format('YYYY-MM-DD HH:MM:SS')
      }
    }
  },
  sort: [{
    [created_at.keyword]: 'asc' // seems to be undefined
  }]
})

Почему я не могу получить доступ к created_at.keyword?

база данных


person Ryan H    schedule 19.02.2021    source источник


Ответы (1)


Ваши даты не должны быть строками / словами, а должны отображаться как как dates . Позвольте мне провести вас через это.

1. Настройте пакет и клиент

const { Client } = require("@elastic/elasticsearch");
const client = new Client({
  node: "http://localhost:9200"
});

const INDEX_NAME = "my_table";

2. Создайте индекс

(async () => {
  const { body, statusCode } = await client.indices.create(
    {
      index: INDEX_NAME,
      body: {
        mappings: {
          properties: {
            created_at: {
              type: "date",
              format: "yyyy-MM-dd HH:mm:ss"
            }
          }
        }
      }
    },
    { ignore: [400] }
  );

  if (body.error) {
    console.warn("createResponse err", body.error);
  } else {
    console.info("createResponse", { body, statusCode });
  }
})();

3. Добавьте документы

(async () => {
  const { body, statusCode } = await client.bulk({
    body: [
      // Doc #1
      { index: { _index: INDEX_NAME, _id: 1 } },
      { created_at: "2021-02-19 00:00:00" },

      // Doc #2
      { index: { _index: INDEX_NAME, _id: 2 } },
      { created_at: "2021-02-19 00:02:00" }
    ]
  });

  if (body.error) {
    console.warn("bulkResponse err", body.error);
  } else {
    console.info("bulkResponse", { body, statusCode });
  }
})();

4. Поиск и сортировка

(async () => {
  const { body, statusCode } = await client.search({
    index: INDEX_NAME,
    body: {
      size: 10,
      query: {
        range: {
          created_at: {
            gte: "2021-02-18 00:00:00"
          }
        }
      },
      sort: [
        {
          created_at: "asc"
        }
      ]
    }
  });

  if (body.error) {
    console.warn("searchResponse err", body.error);
  } else {
    // pretty print
    console.dir({ searchResponse: { body, statusCode } }, { depth: null });
  }
})();

Вот еще несколько официальных примеров. .

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

person Joe Sorocin    schedule 19.02.2021
comment
Имеет ли смысл @Ryan? - person Joe Sorocin; 20.02.2021