Лямбда-поток S3 getObject для ES-конвейера
Я использую лямбду для отправки PDF-файлов, загруженных на S3, в AWS-хост с упругим поиском с помощью подключаемого модуля ES ingest.
Некоторые из файлов PDF могут быть большими - более 100 МБ - и кажется, что было бы лучше для потоковой передачи файлов по частям, а не загружать весь файловый буфер в лямбда-память. Пример кода s3-lambda-es, который я видел, работает с журналами json, которые легко транслировать, но я не видел, чтобы кто-нибудь работал с двоичными документами для плагина ingest.
Примечание: я использую библиотеку elasticssearch-js с http-aws-es connectionClass, чтобы она работала с lambda.
Мой текущий код в основном работает, но он загружает весь PDF перед отправкой в ES. Вот обратный вызов getObject:
s3.getObject({ Bucket: bucket, Key: key }, function(err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
context.fail();
} else {
console.log('data: ', data); // successful response
var attachment = data.Body.toString('base64');
elasticsearch.index(
{
index: 'attachments2',
pipeline: 'pdf_attachment2',
type: 'pdf',
body: {
data: attachment
}
},
function(error, resp) {
if (error) {
console.trace('index error!', error);
} else {
console.log('index response', resp);
context.succeed();
}
}
);
}
});
Есть ли лучший способ для потоковой передачи одного большого документа в ES?
2 ответа
Есть ли лучший способ для потоковой передачи одного большого документа в ES?
Краткий ответ: нет, используйте s3.getObject
Длинный ответ: да, читайте ниже
Прежде всего, ограничение - Elasticsearch. Он просто не предоставляет никакого потокового API. Если вы попытаетесь найти документацию по API, вы даже не найдете упоминаний о потоках.
Зачем? Потому что Elasticsearch не предназначен для потоковой передачи больших файлов в него!
По умолчанию ограничение составляет 100 МБ для тела запроса, которое может быть увеличено до 2 ГБ при настройке. (та же ссылка объясняет, почему вы не должны индексировать такие большие файлы). Короче говоря, у вас будут плохие и нерелевантные результаты поиска, перегрузка ES, использование всей оперативной памяти и так далее.
Более того, вы упомянули, что собираетесь использовать плагин ingest attachment. Если вы перейдете к настройке по умолчанию, вы можете заметить значение по умолчанию: indexed_chars
:
Это означает, что по умолчанию ES не позволяет хранить поля размером более 100 КБ!
Конечно, вы можете переопределить все, настроить ES по своему усмотрению и хранить документы объемом 2 ГБ в 1 полях. Но, как правило, это не рекомендуется.
Рекомендуемый подход состоит в том, чтобы разбить большой pdf на более мелкие куски и проиндексировать их как отдельные документы с одинаковыми documentId
или что угодно. Тогда вы можете де-дупе документы по общим documentId
использование свертывания полей ES (новое в ES 5.3, использование агрегации топ-попаданий в более старых версиях). Это то, что вы не будете в конечном итоге отправить 100 МБ в вашем лямбда.
Итак, подведем итог: вы не можете транслировать в ES большой текст за 1 документ, ES не был предназначен для этого. Но вы можете отправить 100 МБ текста, если хотите. AWS Lambda должна быть в порядке, память будет удалена при необходимости.
@bscandanavia, пожалуйста, поделитесь подходом и кодом, который вы использовали для создания конвейера. Я не могу понять, как мне использовать подключаемый модуль ES ingest attachment.
Извините, что опубликовал это как ответ, потому что у меня нет возможности добавлять комментарии