Coverage Summary for Class: SearchService (org.kitodo.production.services.data.base)
Class |
Method, %
|
Line, %
|
SearchService |
86%
(43/50)
|
52,7%
(135/256)
|
SearchService$1 |
100%
(1/1)
|
100%
(1/1)
|
Total |
86,3%
(44/51)
|
52,9%
(136/257)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.production.services.data.base;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.json.JsonObject;
import javax.ws.rs.HttpMethod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.kitodo.data.database.beans.BaseBean;
import org.kitodo.data.database.beans.BaseIndexedBean;
import org.kitodo.data.database.enums.IndexAction;
import org.kitodo.data.database.exceptions.DAOException;
import org.kitodo.data.database.persistence.BaseDAO;
import org.kitodo.data.elasticsearch.exceptions.CustomResponseException;
import org.kitodo.data.elasticsearch.index.Indexer;
import org.kitodo.data.elasticsearch.index.type.BaseType;
import org.kitodo.data.elasticsearch.search.Searcher;
import org.kitodo.data.elasticsearch.search.enums.SearchCondition;
import org.kitodo.data.exceptions.DataException;
import org.kitodo.production.dto.BaseDTO;
import org.kitodo.production.helper.Helper;
import org.kitodo.production.services.data.ProjectService;
import org.primefaces.model.SortOrder;
/**
* Class for implementing methods used by all service classes which search in
* ElasticSearch index.
*/
public abstract class SearchService<T extends BaseIndexedBean, S extends BaseDTO, V extends BaseDAO<T>>
extends SearchDatabaseService<T, V> {
private static final Logger logger = LogManager.getLogger(SearchService.class);
protected Searcher searcher;
protected Indexer indexer;
protected BaseType type;
protected static final String WILDCARD = "*";
/**
* Constructor necessary to use searcher in child classes.
*
* @param dao
* DAO object for executing operations on database
* @param type
* Type object for ElasticSearch
* @param indexer
* for executing insert / updates to ElasticSearch
* @param searcher
* for executing queries to ElasticSearch
*/
public SearchService(V dao, BaseType type, Indexer indexer, Searcher searcher) {
super(dao);
this.searcher = searcher;
this.indexer = indexer;
this.type = type;
}
/**
* Method converts JSON object object to DTO. Necessary for displaying in the
* frontend.
*
* @param jsonObject
* return from find methods
* @param related
* true or false
* @return DTO object
*/
public abstract S convertJSONObjectToDTO(Map<String, Object> jsonObject, boolean related) throws DataException;
/**
* Count all not indexed rows in database. Not indexed means that row has index
* action INDEX or NULL.
*
* @return amount of all not indexed rows
*/
public abstract Long countNotIndexedDatabaseRows() throws DAOException;
/**
* Get all not indexed objects from database. Not indexed means that row has
* index action INDEX or NULL.
*
* @return list of all not indexed objects
*/
public abstract List<T> getAllNotIndexed();
/**
* Get all not indexed objects from database in given range. Not indexed means
* that row has index action INDEX or NULL.
*
* @param offset
* result - important, numeration starts since 0
* @param size
* amount of results
* @return list of all not indexed objects from database in given range
*/
public List<T> getAllNotIndexed(int offset, int size) throws DAOException {
return dao.getAllNotIndexed(offset, size);
}
/**
* Get all DTO objects from index an convert them for frontend with all
* relations.
*
* @return List of DTO objects
*/
public List<S> findAll() throws DataException {
return findAll(false);
}
/**
* Get all DTO objects from index.
*
* @return List of DTO objects
*/
public List<S> findAll(boolean related) throws DataException {
return convertJSONObjectsToDTOs(findAllDocuments(), related);
}
/**
* Get all ids from index.
*
* @return List of ids
*/
public List<Integer> findAllIDs() throws DataException {
List<Integer> allIds = new ArrayList<>();
for (Map<String, Object> document : findAllDocuments()) {
allIds.add(Integer.parseInt((String) document.get("id")));
}
return allIds;
}
/**
* Get all ids from index in a given range.
*
* @return List of ids in given range
*/
public List<Integer> findAllIDs(Long startIndex, int limit) throws DataException {
List<Integer> allIds = new ArrayList<>();
for (Map<String, Object> document : findAllDocuments(Math.toIntExact(startIndex), limit)) {
allIds.add(Integer.parseInt((String) document.get("id")));
}
return allIds;
}
/**
* Method saves document to the index of Elastic Search.
*
* @param baseIndexedBean
* object
* @param forceRefresh
* force index refresh - if true, time of execution is longer but
* object is right after that available for display
*/
@SuppressWarnings("unchecked")
public void saveToIndex(T baseIndexedBean, boolean forceRefresh)
throws CustomResponseException, DataException, IOException {
indexer.setMethod(HttpMethod.PUT);
if (Objects.nonNull(baseIndexedBean)) {
indexer.performSingleRequest(baseIndexedBean, type, forceRefresh);
}
}
/**
* Method adds all object found in database to Elastic Search index.
*
* @param baseIndexedBeans
* List of BaseIndexedBean objects
*/
@SuppressWarnings("unchecked")
public void addAllObjectsToIndex(List<T> baseIndexedBeans) throws CustomResponseException, DAOException, IOException {
indexer.setMethod(HttpMethod.PUT);
if (!baseIndexedBeans.isEmpty()) {
indexer.performMultipleRequests(baseIndexedBeans, type, false);
saveAsIndexed(baseIndexedBeans);
}
}
/**
* Method removes document from the index of Elastic Search.
*
* @param baseIndexedBean
* object
* @param forceRefresh
* force index refresh - if true, time of execution is longer but
* object is right after that available for display
*/
@SuppressWarnings("unchecked")
public void removeFromIndex(T baseIndexedBean, boolean forceRefresh)
throws CustomResponseException, DataException, IOException {
indexer.setMethod(HttpMethod.DELETE);
if (Objects.nonNull(baseIndexedBean)) {
indexer.performSingleRequest(baseIndexedBean, type, forceRefresh);
}
}
/**
* Method removes document from the index of Elastic Search by given id.
*
* @param id
* of object
* @param forceRefresh
* force index refresh - if true, time of execution is longer but
* object is right after that available for display
*/
public void removeFromIndex(Integer id, boolean forceRefresh) throws CustomResponseException, DataException {
indexer.setMethod(HttpMethod.DELETE);
indexer.performSingleRequest(id, forceRefresh);
}
/**
* Method saves relations which can be potentially modified together with
* object.
*
* @param baseIndexedBean
* object
*/
protected void manageDependenciesForIndex(T baseIndexedBean)
throws CustomResponseException, DAOException, DataException, IOException {
}
/**
* calls save method with default updateRelatedObjectsInIndex=false.
* @param object the object to save
*/
public void save(T object) throws DataException {
save(object, false);
}
/**
* Method saves object to database and document to the index of Elastic Search.
* This method binds three other methods: save to database, save to index and
* save dependencies to index.
*
* <p>
* First step sets up the flag indexAction to state Index and saves to database.
* It informs that object was updated in database but not yet in index. If this
* step fails, method breaks. If it is successful, method saves changes to
* index, first document and next its dependencies. If one of this steps fails,
* method retries up to 5 times operations on index. If it continues to fail,
* method breaks. If save to index was successful, indexAction flag is changed
* to Done and database is again updated. There is possibility that last step
* fails and in that case, even if index is up to date, in some point of the
* future it will be reindexed by administrator.
*
* @param baseIndexedBean
* object
*
* @param updateRelatedObjectsInIndex if relatedObjects need to be updated in Index
*/
public void save(T baseIndexedBean, boolean updateRelatedObjectsInIndex) throws DataException {
try {
baseIndexedBean.setIndexAction(IndexAction.INDEX);
saveToDatabase(baseIndexedBean);
// TODO: find out why properties lists are save double
T savedBean = getById(baseIndexedBean.getId());
saveToIndex(savedBean, true);
if (updateRelatedObjectsInIndex) {
manageDependenciesForIndex(savedBean);
}
savedBean.setIndexAction(IndexAction.DONE);
saveToDatabase(savedBean);
} catch (DAOException e) {
logger.debug(e);
throw new DataException(e);
} catch (CustomResponseException | IOException e) {
int count = 0;
int maxTries = 5;
while (true) {
try {
saveToIndex(baseIndexedBean, true);
manageDependenciesForIndex(baseIndexedBean);
baseIndexedBean.setIndexAction(IndexAction.DONE);
saveToDatabase(baseIndexedBean);
break;
} catch (CustomResponseException | IOException ee) {
logger.debug(ee);
if (++count >= maxTries) {
throw new DataException(ee);
}
} catch (DAOException daoe) {
logger.debug("Index was updated but flag in database not... {}", daoe.getMessage());
throw new DataException(daoe);
}
}
}
}
/**
* Method removes object from database and document from the index of Elastic
* Search.
*
* @param id
* of object
*/
public void remove(Integer id) throws DataException {
try {
T baseIndexedBean = getById(id);
remove(baseIndexedBean);
} catch (DAOException e) {
throw new DataException(e);
}
}
/**
* Method removes object from database and document from the index of Elastic
* Search.
*
* @param baseIndexedBean
* object
*/
public void remove(T baseIndexedBean) throws DataException {
try {
baseIndexedBean.setIndexAction(IndexAction.DELETE);
saveToDatabase(baseIndexedBean);
T savedBean = getById(baseIndexedBean.getId());
removeFromIndex(savedBean, true);
manageDependenciesForIndex(savedBean);
removeFromDatabase(savedBean);
} catch (DAOException e) {
logger.debug(e);
throw new DataException(e);
} catch (CustomResponseException | IOException e) {
int count = 0;
int maxTries = 5;
while (true) {
try {
removeFromIndex(baseIndexedBean, true);
removeFromDatabase(baseIndexedBean);
break;
} catch (CustomResponseException | IOException ee) {
logger.debug(ee);
if (++count >= maxTries) {
throw new DataException(ee);
}
} catch (DAOException daoe) {
logger.debug("Remove from index was successful but...{}", daoe.getMessage());
throw new DataException(daoe);
}
}
}
}
/**
* Count all objects in index.
*
* @return amount of all objects
*/
public Long count() throws DataException {
try {
return searcher.countDocuments();
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Count objects according to given query.
*
* @param query
* for index search
* @return amount of objects according to given query or 0 if query is null
*/
public Long count(QueryBuilder query) throws DataException {
return countDocuments(query);
}
/**
* Display all documents for exact type.
*
* @return list of all documents
*/
public List<Map<String, Object>> findAllDocuments() throws DataException {
QueryBuilder queryBuilder = matchAllQuery();
try {
return searcher.findDocuments(queryBuilder, null, null, Math.toIntExact(count()));
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Display all documents for exact type in a given range.
*
* @return list of all documents from that range
*/
public List<Map<String, Object>> findAllDocuments(Integer offset, Integer size) throws DataException {
QueryBuilder queryBuilder = matchAllQuery();
try {
return searcher.findDocuments(queryBuilder, null, offset, size);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Find object in ES and convert it to DTO.
*
* @param id
* object id
* @return DTO object
*/
public S findById(Integer id) throws DataException {
return findById(id, false);
}
/**
* Find object related to previously found object in ES and convert it to DTO.
*
* @param id
* related object id
* @param related
* this method should ba called only with true, if false call method
* findById(Integer id).
* @return related DTO object
*/
public S findById(Integer id, boolean related) throws DataException {
try {
return convertJSONObjectToDTO(searcher.findDocument(id), related);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Find list of DTO objects by query.
*
* @param query
* as QueryBuilder object
* @param related
* determines if converted object is related to some other object (if
* so, objects related to it are not included in conversion)
* @return list of found DTO objects
*/
public List<S> findByQuery(QueryBuilder query, boolean related) throws DataException {
try {
return convertJSONObjectsToDTOs(searcher.findDocuments(query), related);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Find list of DTO objects by query.
*
* @param query
* as QueryBuilder object
* @param sort
* as String
* @param related
* determines if converted object is related to some other object (if
* so, objects related to it are not included in conversion)
* @return list of found DTO objects
*/
public List<S> findByQuery(QueryBuilder query, SortBuilder sort, boolean related) throws DataException {
try {
return convertJSONObjectsToDTOs(searcher.findDocuments(query, sort), related);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Find list of sorted DTO objects by query with defined offset and size of
* results.
*
* @param query
* as QueryBuilder object
* @param sort
* as String
* @param offset
* as Integer
* @param size
* as Integer
* @param related
* determines if converted object is related to some other object (if
* so, objects related to it are not included in conversion)
* @return list of found DTO objects
*/
public List<S> findByQuery(QueryBuilder query, SortBuilder sort, Integer offset, Integer size, boolean related)
throws DataException {
try {
return convertJSONObjectsToDTOs(searcher.findDocuments(query, sort, offset, size), related);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Convert list of JSONObject object to list of DTO objects.
*
* @param jsonObjects
* list of SearchResult objects
* @param related
* determines if converted object is related to some other object (if
* so, objects related to it are not included in conversion)
* @return list of DTO object
*/
protected List<S> convertJSONObjectsToDTOs(List<Map<String, Object>> jsonObjects, boolean related)
throws DataException {
List<S> results = new ArrayList<>();
for (Map<String, Object> jsonObject : jsonObjects) {
results.add(convertJSONObjectToDTO(jsonObject, related));
}
return results;
}
/**
* Convert related JSONObject object to bean object.
*
* @param jsonObject
* result from ElasticSearch
* @param key
* name of related property
* @return bean object
*/
protected <O extends BaseDTO> List<O> convertRelatedJSONObjectToDTO(Map<String, Object> jsonObject, String key,
SearchService<?, O, ?> service) throws DataException {
List<Integer> ids = getRelatedPropertyForDTO(jsonObject, key);
if (ids.isEmpty()) {
return new ArrayList<>();
}
if (service instanceof ProjectService) {
BoolQueryBuilder query = new BoolQueryBuilder();
query.must(createSetQueryForIds(ids));
query.must(((ProjectService)service).getProjectsForCurrentUserQuery());
return service.findByQuery(query, true);
}
return service.findByQuery(createSetQueryForIds(ids), true);
}
/**
* Builds a ElasticSearch query for list of Ids.
*
* @param ids as a List of Integer
* @return query as QueryBuilder
*/
public QueryBuilder createSetQueryForIds(List<Integer> ids) {
return termsQuery("_id", ids);
}
/**
* Get id from JSON object returned form ElasticSearch.
*
* @param jsonObject
* returned form ElasticSearch
* @return id as Integer
*/
public Integer getIdFromJSONObject(Map<String, Object> jsonObject) {
if (jsonObject.containsKey("id")) {
String id = (String) jsonObject.get("id");
if (Objects.nonNull(id)) {
return Integer.valueOf(id);
}
}
return 0;
}
protected Long countDocuments(QueryBuilder query) throws DataException {
try {
return searcher.countDocuments(query);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Create query for set of data.
*
* @param key
* JSON key for searched object
* @param values
* set of values for searched objects or some objects related to
* searched object
* @param contains
* determine if results should contain given value or should not
* contain given value
* @return query
*/
protected QueryBuilder createSetQuery(String key, Set<?> values, boolean contains) {
if (contains && !values.isEmpty()) {
return termsQuery(key, values);
} else if (!contains && Objects.nonNull(values)) {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
return boolQuery.mustNot(termsQuery(key, values));
} else {
return matchQuery(key, 0);
}
}
protected QueryBuilder createSetQuery(String key, List<Map<String, Object>> values, boolean contains) {
Set<Integer> valuesIds = new HashSet<>();
for (Map<String, Object> value : values) {
valuesIds.add(getIdFromJSONObject(value));
}
return createSetQuery(key, valuesIds, contains);
}
protected QueryBuilder createSetQueryForBeans(String key, List<? extends BaseBean> values, boolean contains) {
Set<Integer> valuesIds = new HashSet<>();
for (BaseBean value : values) {
valuesIds.add(value.getId());
}
return createSetQuery(key, valuesIds, contains);
}
/**
* Used for cases where operator is not necessary to create query - checking
* only for one parameter.
*
* @param key
* JSON key for searched object
* @param id
* id value for searched object or some object related to searched
* object
* @param contains
* determine if results should contain given value or should not
* contain given value
* @return query
*/
protected QueryBuilder createSimpleQuery(String key, Integer id, boolean contains) {
if (contains && Objects.nonNull(id)) {
return matchQuery(key, id);
} else if (!contains && Objects.nonNull(id)) {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
return boolQuery.mustNot(matchQuery(key, id));
} else {
return matchQuery(key, 0);
}
}
/**
* Used for cases where operator is not necessary to create query - checking
* only for one parameter.
*
* @param key
* JSON key for searched object
* @param condition
* id value for searched object or some object related to searched
* object
* @param contains
* determine if results should contain given value or should not
* contain given value
* @return query
*/
protected QueryBuilder createSimpleQuery(String key, Boolean condition, boolean contains) {
if (contains && Objects.nonNull(condition)) {
return matchQuery(key, condition);
} else if (!contains && Objects.nonNull(condition)) {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
return boolQuery.mustNot(matchQuery(key, condition));
} else {
return matchQuery(key, false);
}
}
/**
* Used for cases where operator is not necessary to create query - checking
* only for one parameter.
*
* @param key
* JSON key for searched object
* @param value
* JSON value for searched object
* @param contains
* determine if results should contain given value or should not
* contain given value
* @return query
*/
protected QueryBuilder createSimpleQuery(String key, String value, boolean contains) {
if (contains) {
return matchQuery(key, value);
} else {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
return boolQuery.mustNot(matchQuery(key, value));
}
}
/**
* Used for cases where operator is necessary to create query - checking for
* more than one parameter.
*
* @param key
* JSON key for searched object
* @param value
* JSON value for searched object
* @param contains
* determine if results should contain given value or should not
* contain given value
* @param operator
* as Operator AND or OR - useful when value contains more than one
* word
* @return query
*/
protected QueryBuilder createSimpleQuery(String key, String value, boolean contains, Operator operator) {
if (Objects.isNull(operator)) {
operator = Operator.OR;
}
if (contains) {
return matchQuery(key, value).operator(operator);
} else {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
return boolQuery.mustNot(matchQuery(key, value).operator(operator));
}
}
/**
* Method for comparing dates.
*
* @param key
* as String
* @param date
* as Date
* @param searchCondition
* as SearchCondition - bigger, smaller and so on
* @return query for searching for date in exact range
*/
protected QueryBuilder createSimpleCompareDateQuery(String key, Date date, SearchCondition searchCondition) {
QueryBuilder query = null;
switch (searchCondition) {
case EQUAL:
query = matchQuery(key, Helper.getDateAsFormattedString(date));
break;
case EQUAL_OR_BIGGER:
query = rangeQuery(key).gte(Helper.getDateAsFormattedString(date));
break;
case EQUAL_OR_SMALLER:
query = rangeQuery(key).lte(Helper.getDateAsFormattedString(date));
break;
case BIGGER:
query = rangeQuery(key).gt(Helper.getDateAsFormattedString(date));
break;
case SMALLER:
query = rangeQuery(key).lt(Helper.getDateAsFormattedString(date));
break;
default:
assert false : searchCondition;
}
return query;
}
/**
* Method for comparing Integer values.
*
* @param key
* as String
* @param value
* as Integer
* @param searchCondition
* as SearchCondition - bigger, smaller and so on
* @return query for searching for numbers in exact range
*/
protected QueryBuilder createSimpleCompareQuery(String key, Integer value, SearchCondition searchCondition) {
QueryBuilder query = null;
switch (searchCondition) {
case EQUAL:
query = matchQuery(key, value);
break;
case EQUAL_OR_BIGGER:
query = rangeQuery(key).gte(value);
break;
case EQUAL_OR_SMALLER:
query = rangeQuery(key).lte(value);
break;
case BIGGER:
query = rangeQuery(key).gt(value);
break;
case SMALLER:
query = rangeQuery(key).lt(value);
break;
default:
assert false : searchCondition;
}
return query;
}
protected QueryBuilder createSimpleWildcardQuery(String key, String value) {
return queryStringQuery(key + ".keyword: *" + value + "*");
}
protected Long findCountAggregation(QueryBuilder query, String field) throws DataException {
try {
Aggregations jsonObject = searcher.aggregateDocuments(query, AggregationBuilders.count(field).field(field));
JsonObject count = jsonObject.get(field);
return count.getJsonNumber("value").longValue();
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
protected Double findSumAggregation(QueryBuilder query, String field) throws DataException {
try {
Aggregations jsonObject = searcher.aggregateDocuments(query, AggregationBuilders.count(field).field(field));
JsonObject sum = jsonObject.get(field);
return sum.getJsonNumber("value").doubleValue();
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Find distinct values sorted by terms. Returned values are stored as Strings.
*
* @param query
* for searched values to aggregation
* @param field
* by which aggregation is going to be performed
* @param sort
* asc true or false
* @param size
* number of rows returned by query
* @return sorted list of distinct values
*/
protected List<String> findDistinctValues(QueryBuilder query, String field, boolean sort, long size) throws DataException {
List<String> distinctValues = new ArrayList<>();
try {
TermsAggregationBuilder termsAggregation = AggregationBuilders.terms(field).field(field)
.order(BucketOrder.aggregation("_key", sort));
if (size > 0) {
termsAggregation.size(Math.toIntExact(size));
}
Aggregations jsonObject = searcher.aggregateDocuments(query, termsAggregation);
ParsedStringTerms stringTerms = jsonObject.get(field);
List<? extends Terms.Bucket> buckets = stringTerms.getBuckets();
for (Terms.Bucket bucket : buckets) {
distinctValues.add(bucket.getKeyAsString());
}
return distinctValues;
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
protected Map<String, Object> findDocument(QueryBuilder query) throws DataException {
try {
return searcher.findDocument(query);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
protected List<Map<String, Object>> findDocuments(QueryBuilder query) throws DataException {
return findDocuments(query, null);
}
protected List<Map<String, Object>> findDocuments(QueryBuilder query, SortBuilder sortBuilder) throws DataException {
return findDocuments(query, sortBuilder, null, null);
}
protected List<Map<String, Object>> findDocuments(QueryBuilder query, SortBuilder sortBuilder, Integer offset, Integer size)
throws DataException {
try {
return searcher.findDocuments(query, sortBuilder, offset, size);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}
/**
* Converts properties' values returned from ElasticSearch index.
*
* @param object
* JSONObject
* @return display properties as list of Integers
*/
@SuppressWarnings("unchecked")
private List<Integer> getRelatedPropertyForDTO(Map<String, Object> object, String key) {
if (Objects.nonNull(object)) {
List<Map<String, Object>> jsonArray = (List<Map<String, Object>>) object.get(key);
List<Integer> ids = new ArrayList<>();
for (Map<String, Object> singleObject : jsonArray) {
ids.add((Integer) singleObject.get("id"));
}
return ids;
}
return new ArrayList<>();
}
protected SortBuilder getSortBuilder(String sortField, SortOrder sortOrder) {
if (!Objects.equals(sortField, null) && Objects.equals(sortOrder, SortOrder.ASCENDING)) {
return SortBuilders.fieldSort(sortField).order(org.elasticsearch.search.sort.SortOrder.ASC);
} else if (!Objects.equals(sortField, null) && Objects.equals(sortOrder, SortOrder.DESCENDING)) {
return SortBuilders.fieldSort(sortField).order(org.elasticsearch.search.sort.SortOrder.DESC);
} else {
return null;
}
}
/**
* Removes all objects from index, which are no longer in Database.
* @param baseIndexedBeansId the list of beans to check for missing db eintries.
*
*/
public void removeLooseIndexData(List<Integer> baseIndexedBeansId) throws DataException, CustomResponseException {
for (Integer baseIndexedBeanId : baseIndexedBeansId) {
try {
getById(baseIndexedBeanId);
} catch (DAOException e) {
removeFromIndex(baseIndexedBeanId,true);
}
}
}
}