загрузка данных в Elasticsearch v7.3 с помощью Bulk API - PullRequest
1 голос
/ 04 мая 2020

Мне нужно загрузить данные в индекс эластичного поиска. Я использую BULK API из эластичного поиска для загрузки JSON в индекс.

private String FOLDER_PATH = "src/main/resources/allJsons";
    private String index = "test1";
    private static final String TYPE = "test_type";

 @Autowired
    private RestHighLevelClient restHighLevelClient;

 public String loadBulkData() throws IOException {

        BulkRequest bulkRequest = new BulkRequest();
        AtomicInteger counter = new AtomicInteger();
        try (Stream<Path> filePathStream = Files.walk(Paths.get(FOLDER_PATH))) {
            filePathStream.forEach(filePath -> {
                if (Files.isRegularFile(filePath)) {
                    counter.getAndIncrement();
                    try {
                        String content = Files.readString(filePath);
                        JSONObject jsonObject1 = new JSONObject(content);
                        HashMap yourHashMap1 = new Gson().fromJson(jsonObject1.toString(), HashMap.class);
                        IndexRequest indexRequest = new IndexRequest(index, TYPE).source(yourHashMap1);
                        bulkRequest.add(indexRequest);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }


                }
            });
        }
        try {
            restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "Bulk data loaded to index " + index + "";
    }
}

У меня есть несколько JSON, основанных на следующем формате

[
 {
  "Nutrient" : "Calories",
  "Amount" : " 289.00",
  "Unit" : " kcal"
}, {
  "Nutrient" : "Fat",
  "Amount" : " 17.35",
  "Unit" : " g"
}
]

Во время выполнения кода это выдает ошибку,

org.springframework.web.util.NestedServletException: обработка запроса не удалась; вложенное исключение - org. json .JSONException: текст JSONObject должен начинаться с '{' с 1 [строка 2 символа 1]

Я думаю, что данные находятся в JSONArray и для кода нам нужно JSONObject. Кто-нибудь может, пожалуйста, руководство, как это сделать

1 Ответ

1 голос
/ 04 мая 2020

Вы можете выполнить массовую вставку, передав хеш-карту ваших json объектов в Elasticsearch Bulk API. Вы можете создать Hashmap, проанализировав файл JSON через JSONParser.

Вот код для того же самого:

Код:

          Integer id= 1;

          //You need to call this method for inserting bulk documents which 
          // internally calls `createBulkRequest` and `parseObjectList` methods.
          //This method uses JSONParser to parse your file and convert into JSONArray.
           public String insertBulkDocuments() throws Exception {
                Object obj = new JSONParser().parse(new FileReader(<path-of-file>)); 
                JSONArray objList= (JSONArray) obj;       
                BulkRequest request = createBulkRequest(objList);
                BulkResponse bulkresp=restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
                return bulkresp.status().toString();
            }

            // Each JSONArray element that was obtained through first method 
           //is parsed individually through Gson and converted into you defined Object. 
           //This object is then converted to Map and passed to IndexRequest object.
            private BulkRequest createBulkRequest(JSONArray objList) {
                BulkRequest request = new BulkRequest();
                objList.forEach( obj -> parseObjectList((JSONObject) obj, request,id++));
                return request;
            }

            private void parseObjectList(JSONObject obj, BulkRequest request, int id) {
                Gson gson = new GsonBuilder().create();
                NutrientDocument doc = gson.fromJson(obj.toJSONString(), NutrientDocument .class);

                Map<String, Object> documentMapper = objectMapper.convertValue(doc, Map.class);

                IndexRequest indexRequest = new IndexRequest(<your-index-name>).id(Integer.toString(id)).source(documentMapper);
                request.add(indexRequest);
            }

Вам необходимо создать Custom объект, который имеет те же поля, что и ваш json. Я создал NutrientDocument для тестирования, который имеет те же поля, что и ваш JSON, и я использую его в методе parseObjectList.

public class NutrientDocument {
    private String Nutrient;
    private Float Amount;
    private String Unit;
    public String getNutrient() {
        return Nutrient;
    }
    public void setNutrient(String nutrient) {
        Nutrient = nutrient;
    }
    public Float getAmount() {
        return Amount;
    }
    public void setAmount(Float amount) {
        Amount = amount;
    }
    public String getUnit() {
        return Unit;
    }
    public void setUnit(String unit) {
        Unit = unit;
    }



}

ПРИМЕЧАНИЕ:

Для каждый документasticserach генерирует уникальный id.

Для создания собственного значения id вместо автоматически сгенерированного значения Elasticsearch мы используем переменную id. Но если вы хотите go с автоматически сгенерированным числом Elasticsearch, вы можете создать IndexRequest объект, как показано ниже в методе parseObjectList, и удалить переменную id везде, где мы передаем.

IndexRequest indexRequest = new IndexRequest () .source (documentMapper);

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