diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java index 94507978b..17579abb0 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java @@ -271,7 +271,7 @@ public HtmlResponse edit(final EditForm form) { public HtmlResponse create(final CreateForm form) { verifyCrudMode(form.crudMode, CrudMode.CREATE); validate(form, messages -> {}, this::asEditHtml); - validateFields(form, v -> throwValidationError(v, this::asEditHtml)); + validateFields(form.doc, v -> throwValidationError(v, this::asEditHtml)); verifyToken(this::asEditHtml); getDoc(form).ifPresent(entity -> { try { @@ -299,7 +299,7 @@ public HtmlResponse create(final CreateForm form) { public HtmlResponse update(final EditForm form) { verifyCrudMode(form.crudMode, CrudMode.EDIT); validate(form, messages -> {}, this::asEditHtml); - validateFields(form, v -> throwValidationError(v, this::asEditHtml)); + validateFields(form.doc, v -> throwValidationError(v, this::asEditHtml)); verifyToken(this::asEditHtml); getDoc(form).ifPresent(entity -> { final String index = fessConfig.getIndexDocumentUpdateIndex(); @@ -334,37 +334,37 @@ public HtmlResponse update(final EditForm form) { // =================================================================================== // Validation // ========= - public static void validateFields(final CreateForm form, final Consumer> throwError) { + public static void validateFields(final Map doc, final Consumer> throwError) { final FessConfig fessConfig = ComponentUtil.getFessConfig(); try { - if (!fessConfig.validateIndexRequiredFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexRequiredFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexRequiredFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexRequiredFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyRequired(s, s))); } - if (!fessConfig.validateIndexArrayFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexArrayFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexArrayFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexArrayFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyRequired(s, s))); } - if (!fessConfig.validateIndexDateFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexDateFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexDateFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexDateFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyTypeDate(s, s))); } - if (!fessConfig.validateIndexIntegerFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexIntegerFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexIntegerFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexIntegerFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyTypeInteger(s, s))); } - if (!fessConfig.validateIndexLongFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexLongFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexLongFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexLongFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyTypeLong(s, s))); } - if (!fessConfig.validateIndexFloatFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexFloatFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexFloatFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexFloatFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyTypeFloat(s, s))); } - if (!fessConfig.validateIndexDoubleFields(form.doc)) { - throwError.accept(messages -> fessConfig.invalidIndexDoubleFields(form.doc).stream().map(s -> "doc." + s) + if (!fessConfig.validateIndexDoubleFields(doc)) { + throwError.accept(messages -> fessConfig.invalidIndexDoubleFields(doc).stream().map(s -> "doc." + s) .forEach(s -> messages.addErrorsPropertyTypeDouble(s, s))); } } catch (final Exception e) { diff --git a/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java b/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java index 2d6145f82..c66569236 100644 --- a/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java +++ b/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java @@ -39,7 +39,7 @@ public ApiResult(final ApiResponse response) { } public enum Status { - OK(0), BAD_REQUEST(1), SYSTEM_ERROR(2), UNAUTHORIZED(3); + OK(0), BAD_REQUEST(1), SYSTEM_ERROR(2), UNAUTHORIZED(3), FAILED(9); private final int id; @@ -391,4 +391,18 @@ public ApiResult result() { return new ApiResult(this); } } + + public static class ApiBulkResponse extends ApiResponse { + protected List> items; + + public ApiBulkResponse items(final List> items) { + this.items = items; + return this; + } + + @Override + public ApiResult result() { + return new ApiResult(this); + } + } } diff --git a/src/main/java/org/codelibs/fess/app/web/api/admin/documents/ApiAdminDocumentsAction.java b/src/main/java/org/codelibs/fess/app/web/api/admin/documents/ApiAdminDocumentsAction.java new file mode 100644 index 000000000..74e74dc7e --- /dev/null +++ b/src/main/java/org/codelibs/fess/app/web/api/admin/documents/ApiAdminDocumentsAction.java @@ -0,0 +1,110 @@ +/* + * Copyright 2012-2024 CodeLibs Project and the Others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.codelibs.fess.app.web.api.admin.documents; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.codelibs.fess.app.web.admin.searchlist.AdminSearchlistAction; +import org.codelibs.fess.app.web.api.ApiResult; +import org.codelibs.fess.app.web.api.ApiResult.ApiBulkResponse; +import org.codelibs.fess.app.web.api.ApiResult.Status; +import org.codelibs.fess.app.web.api.admin.FessApiAdminAction; +import org.codelibs.fess.app.web.api.admin.searchlist.ApiAdminSearchlistAction; +import org.codelibs.fess.es.client.SearchEngineClient; +import org.codelibs.fess.helper.CrawlingConfigHelper; +import org.codelibs.fess.helper.CrawlingInfoHelper; +import org.codelibs.fess.thumbnail.ThumbnailManager; +import org.codelibs.fess.util.ComponentUtil; +import org.lastaflute.web.Execute; +import org.lastaflute.web.response.JsonResponse; +import org.opensearch.action.bulk.BulkResponse; + +public class ApiAdminDocumentsAction extends FessApiAdminAction { + // =================================================================================== + // Constant + // + private static final Logger logger = LogManager.getLogger(ApiAdminSearchlistAction.class); + + // =================================================================================== + // Attribute + // ========= + @Resource + protected SearchEngineClient searchEngineClient; + + // =================================================================================== + // Search Execute + // + + // POST /api/admin/documents/bulk + @Execute + public JsonResponse post$bulk(final BulkBody body) { + validateApi(body, messages -> {}); + if (body.documents == null) { + throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "documents is required.")); + } + if (body.documents.isEmpty()) { + throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "documents is empty.")); + } + final String indexFieldId = fessConfig.getIndexFieldId(); + final CrawlingInfoHelper crawlingInfoHelper = ComponentUtil.getCrawlingInfoHelper(); + final List> docList = body.documents.stream().map(doc -> { + AdminSearchlistAction.validateFields(doc, this::throwValidationErrorApi); + final Map newDoc = fessConfig.convertToStorableDoc(doc); + final String newId = crawlingInfoHelper.generateId(newDoc); + newDoc.put(indexFieldId, newId); + return newDoc; + }).toList(); + if (fessConfig.isThumbnailCrawlerEnabled()) { + final ThumbnailManager thumbnailManager = ComponentUtil.getThumbnailManager(); + final String thumbnailField = fessConfig.getIndexFieldThumbnail(); + docList.stream().forEach(doc -> { + if (!thumbnailManager.offer(doc)) { + if (logger.isDebugEnabled()) { + logger.debug("Removing {}={} from doc[{}]", thumbnailField, doc.get(thumbnailField), + doc.get(fessConfig.getIndexFieldUrl())); + } + doc.remove(thumbnailField); + } + }); + } + + final CrawlingConfigHelper crawlingConfigHelper = ComponentUtil.getCrawlingConfigHelper(); + final BulkResponse response = searchEngineClient.addAll(fessConfig.getIndexDocumentUpdateIndex(), docList, (doc, builder) -> { + if (doc.get(fessConfig.getIndexFieldConfigId()) instanceof final String configId) { + crawlingConfigHelper.getPipeline(configId).ifPresent(s -> builder.setPipeline(s)); + } + }); + return asJson(new ApiBulkResponse().items(Arrays.stream(response.getItems()).map(item -> { + final Map itemMap = new HashMap<>(); + itemMap.put("status", item.status().name()); + if (item.isFailed()) { + itemMap.put("message", item.getFailureMessage()); + } else { + itemMap.put("id", item.getId()); + } + return itemMap; + }).toList()).status(response.hasFailures() ? Status.FAILED : Status.OK).result()); + + } + +} diff --git a/src/main/java/org/codelibs/fess/app/web/api/admin/documents/BulkBody.java b/src/main/java/org/codelibs/fess/app/web/api/admin/documents/BulkBody.java new file mode 100644 index 000000000..a67199fd3 --- /dev/null +++ b/src/main/java/org/codelibs/fess/app/web/api/admin/documents/BulkBody.java @@ -0,0 +1,25 @@ +/* + * Copyright 2012-2024 CodeLibs Project and the Others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.codelibs.fess.app.web.api.admin.documents; + +import java.util.List; +import java.util.Map; + +public class BulkBody { + + public List> documents; + +} diff --git a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java index 114f44b82..1017d911f 100644 --- a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java +++ b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java @@ -120,7 +120,7 @@ public JsonResponse docs(final SearchBody body) { if (body.doc == null) { throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "doc is required")); } - validateFields(body, this::throwValidationErrorApi); + validateFields(body.doc, this::throwValidationErrorApi); body.crudMode = CrudMode.CREATE; final Map doc = getDoc(body).map(entity -> { try { @@ -152,7 +152,7 @@ public JsonResponse docs(final SearchBody body) { if (body.doc == null) { throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "doc is required")); } - validateFields(body, this::throwValidationErrorApi); + validateFields(body.doc, this::throwValidationErrorApi); body.crudMode = CrudMode.EDIT; final Map doc = getDoc(body).map(entity -> { final String index = fessConfig.getIndexDocumentUpdateIndex(); diff --git a/src/main/java/org/codelibs/fess/es/client/SearchEngineClient.java b/src/main/java/org/codelibs/fess/es/client/SearchEngineClient.java index 186c491af..84f484b6a 100644 --- a/src/main/java/org/codelibs/fess/es/client/SearchEngineClient.java +++ b/src/main/java/org/codelibs/fess/es/client/SearchEngineClient.java @@ -84,7 +84,6 @@ import org.opensearch.OpenSearchStatusException; import org.opensearch.action.ActionRequest; import org.opensearch.action.ActionType; -import org.opensearch.action.DocWriteRequest; import org.opensearch.action.DocWriteRequest.OpType; import org.opensearch.action.DocWriteResponse.Result; import org.opensearch.action.admin.cluster.health.ClusterHealthResponse; @@ -97,8 +96,6 @@ import org.opensearch.action.admin.indices.refresh.RefreshResponse; import org.opensearch.action.admin.indices.segments.IndicesSegmentResponse; import org.opensearch.action.admin.indices.segments.PitSegmentsRequest; -import org.opensearch.action.bulk.BulkItemResponse; -import org.opensearch.action.bulk.BulkItemResponse.Failure; import org.opensearch.action.bulk.BulkRequest; import org.opensearch.action.bulk.BulkRequestBuilder; import org.opensearch.action.bulk.BulkResponse; @@ -1186,7 +1183,7 @@ public PingResponse ping() { } } - public String[] addAll(final String index, final List> docList, + public BulkResponse addAll(final String index, final List> docList, final BiConsumer, IndexRequestBuilder> options) { final FessConfig fessConfig = ComponentUtil.getFessConfig(); final BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); @@ -1196,26 +1193,7 @@ public String[] addAll(final String index, final List> docLi options.accept(doc, builder); bulkRequestBuilder.add(builder); } - final BulkResponse response = bulkRequestBuilder.execute().actionGet(ComponentUtil.getFessConfig().getIndexBulkTimeout()); - if (response.hasFailures()) { - if (logger.isDebugEnabled()) { - final List> requests = bulkRequestBuilder.request().requests(); - final BulkItemResponse[] items = response.getItems(); - if (requests.size() == items.length) { - for (int i = 0; i < requests.size(); i++) { - final BulkItemResponse resp = items[i]; - if (resp.isFailed() && resp.getFailure() != null) { - final DocWriteRequest req = requests.get(i); - final Failure failure = resp.getFailure(); - logger.debug("Failed Request: {}\n=>{}", req, failure.getMessage()); - } - } - } - } - throw new SearchEngineClientException(response.buildFailureMessage()); - } - - return Arrays.stream(response.getItems()).map(BulkItemResponse::getId).toArray(n -> new String[n]); + return bulkRequestBuilder.execute().actionGet(ComponentUtil.getFessConfig().getIndexBulkTimeout()); } public static class SearchConditionBuilder { diff --git a/src/main/java/org/codelibs/fess/helper/IndexingHelper.java b/src/main/java/org/codelibs/fess/helper/IndexingHelper.java index 141ce4c81..368abe520 100644 --- a/src/main/java/org/codelibs/fess/helper/IndexingHelper.java +++ b/src/main/java/org/codelibs/fess/helper/IndexingHelper.java @@ -23,12 +23,16 @@ import org.apache.logging.log4j.Logger; import org.apache.lucene.search.TotalHits; import org.codelibs.fess.es.client.SearchEngineClient; +import org.codelibs.fess.es.client.SearchEngineClientException; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.thumbnail.ThumbnailManager; import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.DocList; import org.codelibs.fess.util.MemoryUtil; import org.opensearch.action.admin.indices.refresh.RefreshResponse; +import org.opensearch.action.bulk.BulkItemResponse; +import org.opensearch.action.bulk.BulkItemResponse.Failure; +import org.opensearch.action.bulk.BulkResponse; import org.opensearch.action.search.SearchResponse; import org.opensearch.index.query.QueryBuilder; import org.opensearch.index.query.QueryBuilders; @@ -72,10 +76,27 @@ public void sendDocuments(final SearchEngineClient searchEngineClient, final Doc if (logger.isDebugEnabled()) { logger.debug("Deleted {} old docs", deletedDocCount); } - searchEngineClient.addAll(fessConfig.getIndexDocumentUpdateIndex(), docList, (doc, builder) -> { - final String configId = (String) doc.get(fessConfig.getIndexFieldConfigId()); - crawlingConfigHelper.getPipeline(configId).ifPresent(s -> builder.setPipeline(s)); - }); + final BulkResponse response = + searchEngineClient.addAll(fessConfig.getIndexDocumentUpdateIndex(), docList, (doc, builder) -> { + final String configId = (String) doc.get(fessConfig.getIndexFieldConfigId()); + crawlingConfigHelper.getPipeline(configId).ifPresent(s -> builder.setPipeline(s)); + }); + if (response.hasFailures()) { + if (logger.isDebugEnabled()) { + final BulkItemResponse[] items = response.getItems(); + if (docList.size() == items.length) { + for (int i = 0; i < docList.size(); i++) { + final BulkItemResponse resp = items[i]; + if (resp.isFailed() && resp.getFailure() != null) { + final Map req = docList.get(i); + final Failure failure = resp.getFailure(); + logger.debug("Failed Request: {}\n=>{}", req, failure.getMessage()); + } + } + } + } + throw new SearchEngineClientException(response.buildFailureMessage()); + } } if (logger.isInfoEnabled()) { if (docList.getContentSize() > 0) { diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java index 70ff5c94f..e108c23a0 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java @@ -1362,9 +1362,14 @@ default boolean validateIndexIntegerFields(final Map source) { default List invalidIndexIntegerFields(final Map source) { final IntegerTypeValidator integerValidator = new IntegerTypeValidator(); - return split(getIndexAdminIntegerFields(), ",") - .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))) - .filter(s -> !integerValidator.isValid(source.get(s).toString(), null)).collect(Collectors.toList())); + return split(getIndexAdminIntegerFields(), ",").get( + stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))).filter(s -> { + final Object obj = source.get(s); + if (obj instanceof Number) { + return false; + } + return !integerValidator.isValid(obj.toString(), null); + }).collect(Collectors.toList())); } String getIndexAdminLongFields(); @@ -1386,9 +1391,14 @@ default boolean validateIndexLongFields(final Map source) { default List invalidIndexLongFields(final Map source) { final LongTypeValidator longValidator = new LongTypeValidator(); - return split(getIndexAdminLongFields(), ",") - .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))) - .filter(s -> !longValidator.isValid(source.get(s).toString(), null)).collect(Collectors.toList())); + return split(getIndexAdminLongFields(), ",").get( + stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))).filter(s -> { + final Object obj = source.get(s); + if (obj instanceof Number) { + return false; + } + return !longValidator.isValid(obj.toString(), null); + }).collect(Collectors.toList())); } String getIndexAdminFloatFields(); @@ -1410,9 +1420,13 @@ default boolean validateIndexFloatFields(final Map source) { default List invalidIndexFloatFields(final Map source) { final FloatTypeValidator floatValidator = new FloatTypeValidator(); - return split(getIndexAdminFloatFields(), ",") - .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))) - .filter(s -> !floatValidator.isValid(source.get(s).toString(), null)).collect(Collectors.toList())); + return split(getIndexAdminFloatFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> { + final Object obj = source.get(s); + if (obj instanceof Number) { + return false; + } + return !floatValidator.isValid(obj.toString(), null); + }).collect(Collectors.toList())); } String getIndexAdminDoubleFields(); @@ -1434,9 +1448,13 @@ default boolean validateIndexDoubleFields(final Map source) { default List invalidIndexDoubleFields(final Map source) { final DoubleTypeValidator doubleValidator = new DoubleTypeValidator(); - return split(getIndexAdminDoubleFields(), ",") - .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))) - .filter(s -> !doubleValidator.isValid(source.get(s).toString(), null)).collect(Collectors.toList())); + return split(getIndexAdminDoubleFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> { + final Object obj = source.get(s); + if (obj instanceof Number) { + return false; + } + return !doubleValidator.isValid(obj.toString(), null); + }).collect(Collectors.toList())); } default Map convertToEditableDoc(final Map source) { @@ -1488,19 +1506,41 @@ default Map convertToStorableDoc(final Map sourc final String key = e.getKey(); Object value = e.getValue(); if (arrayFieldSet.contains(key)) { - value = split(value.toString(), "\n") - .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toList())); + if (value instanceof String[]) { + value = Arrays.stream((String[]) value).toList(); + } else if (value instanceof List) { + // nothing + } else { + value = split(value.toString(), "\n") + .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toList())); + } } else if (dateFieldSet.contains(key)) { // TODO time zone value = FessFunctions.parseDate(value.toString()); } else if (integerFieldSet.contains(key)) { - value = DfTypeUtil.toInteger(value.toString()); + if (value instanceof Number num) { + value = num.intValue(); + } else { + value = DfTypeUtil.toInteger(value.toString()); + } } else if (longFieldSet.contains(key)) { - value = DfTypeUtil.toLong(value.toString()); + if (value instanceof Number num) { + value = num.longValue(); + } else { + value = DfTypeUtil.toLong(value.toString()); + } } else if (floatFieldSet.contains(key)) { - value = DfTypeUtil.toFloat(value.toString()); + if (value instanceof Number num) { + value = num.floatValue(); + } else { + value = DfTypeUtil.toFloat(value.toString()); + } } else if (doubleFieldSet.contains(key)) { - value = DfTypeUtil.toDouble(value.toString()); + if (value instanceof Number num) { + value = num.doubleValue(); + } else { + value = DfTypeUtil.toDouble(value.toString()); + } } return new Pair<>(key, value); }).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); diff --git a/src/test/java/org/codelibs/fess/helper/IndexingHelperTest.java b/src/test/java/org/codelibs/fess/helper/IndexingHelperTest.java index de9143e59..1e7efd1d5 100644 --- a/src/test/java/org/codelibs/fess/helper/IndexingHelperTest.java +++ b/src/test/java/org/codelibs/fess/helper/IndexingHelperTest.java @@ -33,6 +33,8 @@ import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.DocList; import org.dbflute.optional.OptionalEntity; +import org.opensearch.action.bulk.BulkItemResponse; +import org.opensearch.action.bulk.BulkResponse; import org.opensearch.action.index.IndexAction; import org.opensearch.action.index.IndexRequestBuilder; import org.opensearch.action.search.SearchAction; @@ -87,12 +89,12 @@ public void test_sendDocuments() { final List> sentDocList = new ArrayList<>(); final SearchEngineClient client = new SearchEngineClient() { @Override - public String[] addAll(final String index, final List> docList, + public BulkResponse addAll(final String index, final List> docList, final BiConsumer, IndexRequestBuilder> options) { sentIndex.set(index); docList.forEach(x -> options.accept(x, new IndexRequestBuilder(this, IndexAction.INSTANCE))); sentDocList.addAll(docList); - return docList.stream().map(x -> (String) x.get("id")).toArray(n -> new String[n]); + return new BulkResponse(new BulkItemResponse[0], documentSizeByQuery); } @Override