Подтвердить что ты не робот

Импорт 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"

Некоторые дали ошибку, другие не сделали. Что мне нужно сделать?

4b9b3361

Ответ 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"