Импорт JSON Bulk в Elasticstearch
Elasticsearch Массовый импорт.
Мне нужно импортировать Продукты как отдельные элементы.
У меня есть json файл, который выглядит примерно так:
{
"Products":[
{
"Title":"Product 1",
"Description":"Product 1 Description",
"Size":"Small",
"Location":[
{
"url":"website.com",
"price":"9.99",
"anchor":"Prodcut 1"
}
],
"Images":[
{
"url":"product1.jpg"
}
],
"Slug":"prodcut1"
},
{
"Title":"Product 2",
"Description":"Prodcut 2 Desctiption",
"Size":"large",
"Location":[
{
"url":"website2.com",
"price":"99.94",
"anchor":"Product 2"
},
{
"url":"website3.com",
"price":"79.95",
"anchor":"discount product 2"
}
],
"Images":[
{
"url":"image.jpg"
},
{
"url":"image2.jpg"
}
],
"Slug":"product2"
}
]
}
Я пробовал следующее (я новичок в этом):
curl -s -XPOST 'http://localhost:9200/_bulk' --data-binary @products.json
curl -s -XPOST 'http://localhost:9200/_bulk' -d @products.json
curl -XPOST http://localhost:9200/cp/products -d "@products.json"
curl -XPOST http://localhost:9200/products -d "@products.json"
Некоторые дали ошибку, другие не сделали. Что мне нужно сделать?
Ответы
Ответ 1
Следуя Документация Bulk API. Вам необходимо предоставить массовую операцию с форматированием файла очень конкретно:
ПРИМЕЧАНИЕ: окончательная строка данных должна заканчиваться символом новой строки \n.
Возможными действиями являются индекс, создание, удаление и обновление. index и create ожидать источника на следующей строке и иметь ту же семантику, что и параметр op_type, в стандартный индексный API (т.е. create будет терпеть неудачу, если документ с тем же индексом и типом уже существует, тогда как индекс добавит или заменит документ как надо). delete не ожидает источника в следующей строке и имеет ту же семантику, что и стандартный API удаления. update ожидает, что частичный doc, upsert и script и его параметры будут указаны в следующей строке.
Если вы предоставляете ввод текстового файла для завивки, вы должны использовать флаг -data-binary вместо plain -d. Последний не сохраняет символы новой строки.
Поэтому вам нужно будет изменить содержимое вашего файла products.json на следующее:
{"index":{"_index":"cp", "_type":"products", "_id": "1"}}
{ "Title":"Product 1", "Description":"Product 1 Description", "Size":"Small", "Location":[{"url":"website.com", "price":"9.99", "anchor":"Prodcut 1"}],"Images":[{ "url":"product1.jpg"}],"Slug":"prodcut1"}
{"index":{"_index":"cp", "_type":"products", "_id":"2"}}
{"Title":"Product 2", "Description":"Prodcut 2 Desctiption", "Size":"large","Location":[{"url":"website2.com", "price":"99.94","anchor":"Product 2"},{"url":"website3.com","price":"79.95","anchor":"discount product 2"}],"Images":[{"url":"image.jpg"},{"url":"image2.jpg"}],"Slug":"product2"}
И не забудьте использовать --data-binary
в вашей команде curl (как ваша первая команда). Также обратите внимание, что index
и type
могут быть опущены, если вы используете конечную точку с индексом и типом. Ваш /cp/products
как ваша 3-я команда curl.
Ответ 2
В итоге я написал bash script, который "совсем не оптимизирован", чтобы сделать это для меня. Набор данных относительно невелик, поэтому это будет работать для моих нужд.
#!/bin/bash
COUNTER=0
CURLURL="http://127.0.0.1:9200/cp/products"
COUNT=$(less products.json | jq '.Products | length')
while [ $COUNTER -lt $COUNT ]; do
echo $COUNTER
CURLDATA=$(less products.json | jq '.Products['$COUNTER']')
RESPONSE=$(curl -XPOST "$CURLURL" -d "$CURLDATA" -vn)
let COUNTER=COUNTER+1
done
Ответ 3
Мне удалось добавить необходимые заголовки со следующими sed
script:
sed -e 's/^/{ "index" : {} }\n/' -i products.json
Это добавит пустой индекс над каждой строкой в файле. Допускается пустой индекс, если указатель и тип указаны в URL-адресе. После этого правильный вызов будет
curl -s -XPOST http://localhost:9200/cp/products/_bulk --data-binary @products.json
Ответ 4
Это было быстро и работало для меня на массиве объектов JSON.
cat data.json | \
jq -c '.[] | .id = ._id | del (._id) | {"index": {"_index": "profiles", "_type": "gps", "_id": .id}}, .' |\
curl -XPOST 127.0.0.1:9200/_bulk --data-binary @-
Мне нужно было сделать копию и удалить поле _id
, так как импорт забросил ошибку (поле [_id] является полем метаданных и не может быть добавлено внутри документа. Используйте параметры запроса API индекса). Если это не было переименовано. Большинство данных вряд ли имеют поле _id
, и в этом случае эта часть должна быть опущена.
Кредит для этого Кевин Марш
Ответ 5
Другой вариант - использовать инструмент json-to-es-bulk.
Для преобразования вашего файла JSON в NDJSON выполните следующее:
node ./index.js -f file.json --index index_name --type type_name
Он создаст файл request-data.txt
, который можно импортировать с помощью большого объема:
curl -H "Content-Type: application/json" -XPOST "http://localhost:9200/my_index/my_type/_bulk?pretty" --data-binary "@request-data.txt"