Skip to content

Commit

Permalink
Made calculation of the total records count optional for case of matc…
Browse files Browse the repository at this point in the history
…hing by matchedId, externalId, externalHrid
  • Loading branch information
RuslanLavrov committed Feb 6, 2024
1 parent 66a26b5 commit 4f48dec
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public interface RecordDao {
*/
Future<RecordCollection> getRecords(Condition condition, RecordType recordType, Collection<OrderField<?>> orderFields, int offset, int limit, String tenantId);

/**
* Searches for {@link Record} by {@link Condition} and ordered by collection of {@link OrderField} with offset and limit
*
* @param condition query where condition
* @param recordType record type
* @param orderFields fields to order by
* @param offset starting index in a list of results
* @param limit limit of records for pagination
* @param returnTotalCount indicates that total records count should/shouldn't be calculated and returned within {@link RecordCollection#totalRecords}
* @param tenantId tenant id
* @return {@link Future} of {@link RecordCollection}
*/
Future<RecordCollection> getRecords(Condition condition, RecordType recordType, Collection<OrderField<?>> orderFields, int offset, int limit, boolean returnTotalCount, String tenantId);

/**
* Searches for records by {@link Condition} with only {@link ParsedRecord} content
*
Expand Down Expand Up @@ -79,7 +93,7 @@ public interface RecordDao {
*
* @param matchedField describes searching condition
* @param returnTotalRecords indicates that amount of total records should/shouldn't be calculated
* and populated into {@link RecordsIdentifiersCollection.totalRecords}
* and populated into {@link RecordsIdentifiersCollection#totalRecords}
* @param typeConnection record type
* @param externalIdRequired specifies whether necessary not to consider records with {@code externalId == null} while searching
* @param offset offset to skip over a number of elements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
import org.jooq.OrderField;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.ResultQuery;
import org.jooq.SelectConditionStep;
import org.jooq.SelectJoinStep;
import org.jooq.SelectOnConditionStep;
Expand Down Expand Up @@ -228,22 +229,36 @@ public <T> Future<T> executeInTransaction(Function<ReactiveClassicGenericQueryEx

@Override
public Future<RecordCollection> getRecords(Condition condition, RecordType recordType, Collection<OrderField<?>> orderFields, int offset, int limit, String tenantId) {
return getRecords(condition, recordType, orderFields, offset, limit, true, tenantId);
}

@Override
public Future<RecordCollection> getRecords(Condition condition, RecordType recordType, Collection<OrderField<?>> orderFields, int offset, int limit, boolean returnTotalCount, String tenantId) {
Name cte = name(CTE);
Name prt = name(recordType.getTableName());
return getQueryExecutor(tenantId).transaction(txQE -> txQE.query(dsl -> dsl
.with(cte.as(dsl.selectCount()
.from(RECORDS_LB)
.where(condition.and(recordType.getRecordImplicitCondition()))))
.select(getAllRecordFieldsWithCount(prt))
.from(RECORDS_LB)
.leftJoin(table(prt)).on(RECORDS_LB.ID.eq(field(TABLE_FIELD_TEMPLATE, UUID.class, prt, name(ID))))
.leftJoin(RAW_RECORDS_LB).on(RECORDS_LB.ID.eq(RAW_RECORDS_LB.ID))
.leftJoin(ERROR_RECORDS_LB).on(RECORDS_LB.ID.eq(ERROR_RECORDS_LB.ID))
.rightJoin(dsl.select().from(table(cte))).on(trueCondition())
.where(condition.and(recordType.getRecordImplicitCondition()))
.orderBy(orderFields)
.offset(offset)
.limit(limit > 0 ? limit : DEFAULT_LIMIT_FOR_GET_RECORDS)
return getQueryExecutor(tenantId).transaction(txQE -> txQE.query(dsl -> {
ResultQuery<Record1<Integer>> countQuery;
if (returnTotalCount) {
countQuery = dsl.selectCount()
.from(RECORDS_LB)
.where(condition.and(recordType.getRecordImplicitCondition()));
} else {
countQuery = select(inline(null, Integer.class).as(COUNT));
}

return dsl
.with(cte.as(countQuery))
.select(getAllRecordFieldsWithCount(prt))
.from(RECORDS_LB)
.leftJoin(table(prt)).on(RECORDS_LB.ID.eq(field(TABLE_FIELD_TEMPLATE, UUID.class, prt, name(ID))))
.leftJoin(RAW_RECORDS_LB).on(RECORDS_LB.ID.eq(RAW_RECORDS_LB.ID))
.leftJoin(ERROR_RECORDS_LB).on(RECORDS_LB.ID.eq(ERROR_RECORDS_LB.ID))
.rightJoin(dsl.select().from(table(cte))).on(trueCondition())
.where(condition.and(recordType.getRecordImplicitCondition()))
.orderBy(orderFields)
.offset(offset)
.limit(limit > 0 ? limit : DEFAULT_LIMIT_FOR_GET_RECORDS);
}
)).map(queryResult -> toRecordCollectionWithLimitCheck(queryResult, limit));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@
public class RecordServiceImpl implements RecordService {

private static final Logger LOG = LogManager.getLogger();

private final RecordDao recordDao;
private static final String DUPLICATE_CONSTRAINT = "idx_records_matched_id_gen";
private static final String DUPLICATE_RECORD_MSG = "Incoming file may contain duplicates";
private static final String MULTIPLE_MATCHING_FILTERS_SPECIFIED_MSG = "Only one matching filter is allowed in the current API implementation";
private static final String MATCHED_ID_NOT_EQUAL_TO_999_FIELD = "Matched id (%s) not equal to 999ff$s (%s) field";
private static final String RECORD_WITH_GIVEN_MATCHED_ID_NOT_FOUND = "Record with given matched id (%s) not found";
public static final String UPDATE_RECORD_DUPLICATE_EXCEPTION = "Incoming record could be a duplicate, incoming record generation should not be the same as matched record generation and the execution of job should be started after of creating the previous record generation";
Expand Down Expand Up @@ -319,17 +319,16 @@ public Future<RecordsIdentifiersCollection> getMatchedRecordsIdentifiers(RecordM
TypeConnection typeConnection = getTypeConnection(recordMatchingDto.getRecordType());

if (matchField.isDefaultField()) {
return processDefaultMatchField(matchField, tenantId, typeConnection,
recordMatchingDto.getOffset(), recordMatchingDto.getLimit());
return processDefaultMatchField(matchField, typeConnection, recordMatchingDto, tenantId);
}
return recordDao.getMatchedRecordsIdentifiers(matchField, recordMatchingDto.getReturnTotalRecordsCount(), typeConnection, true,
recordMatchingDto.getOffset(), recordMatchingDto.getLimit(), tenantId);
return recordDao.getMatchedRecordsIdentifiers(matchField, recordMatchingDto.getReturnTotalRecordsCount(), typeConnection,
true, recordMatchingDto.getOffset(), recordMatchingDto.getLimit(), tenantId);
}

private MatchField prepareMatchField(RecordMatchingDto recordMatchingDto) {
// only one matching filter is expected in the current implementation for processing records matching
if (recordMatchingDto.getFilters().size() > 1) {
throw new BadRequestException("Only one matching filter is allowed in the current API implementation");
throw new BadRequestException(MULTIPLE_MATCHING_FILTERS_SPECIFIED_MSG);
}

Filter filter = recordMatchingDto.getFilters().get(0);
Expand All @@ -347,8 +346,8 @@ private TypeConnection getTypeConnection(RecordMatchingDto.RecordType recordType
};
}

private Future<RecordsIdentifiersCollection> processDefaultMatchField(MatchField matchField, String tenantId,
TypeConnection typeConnection, Integer offset, Integer limit) {
private Future<RecordsIdentifiersCollection> processDefaultMatchField(MatchField matchField, TypeConnection typeConnection,
RecordMatchingDto recordMatchingDto, String tenantId) {
Condition condition = filterRecordByState(Record.State.ACTUAL.value());
List<String> values = ((ListValue) matchField.getValue()).getValue();

Expand All @@ -360,7 +359,8 @@ private Future<RecordsIdentifiersCollection> processDefaultMatchField(MatchField
condition = condition.and(filterRecordByExternalHridValues(values));
}

return recordDao.getRecords(condition, typeConnection.getDbType(), Collections.emptyList(), offset, limit, tenantId)
return recordDao.getRecords(condition, typeConnection.getDbType(), Collections.emptyList(), recordMatchingDto.getOffset(),
recordMatchingDto.getLimit(), recordMatchingDto.getReturnTotalRecordsCount(), tenantId)
.map(recordCollection -> recordCollection.getRecords().stream()
.map(sourceRecord -> new RecordIdentifiersDto()
.withRecordId(sourceRecord.getId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,4 +451,27 @@ public void shouldNotReturnTotalRecordsIfReturnTotalRecordsIsFalse(TestContext c
.body("identifiers.size()", is(expectedRecordCount));
}

@Test
public void shouldNotReturnTotalRecordsIfReturnTotalRecordsIsFalseAndMatchingByMatchedIdField() {
RestAssured.given()
.spec(spec)
.when()
.body(new RecordMatchingDto()
.withReturnTotalRecordsCount(false)
.withRecordType(RecordMatchingDto.RecordType.MARC_BIB)
.withFilters(List.of(new Filter()
.withValues(List.of(existingRecord.getMatchedId()))
.withField("999")
.withIndicator1("f")
.withIndicator2("f")
.withSubfield("s"))))
.post(RECORDS_MATCHING_PATH)
.then()
.statusCode(HttpStatus.SC_OK)
.body("totalRecords", nullValue())
.body("identifiers.size()", is(1))
.body("identifiers[0].recordId", is(existingRecord.getId()))
.body("identifiers[0].externalId", is(existingRecord.getExternalIdsHolder().getInstanceId()));
}

}

0 comments on commit 4f48dec

Please sign in to comment.