Skip to content

Commit

Permalink
Multiple Queries Experiment
Browse files Browse the repository at this point in the history
RISDEV-2961
  • Loading branch information
HPrinz committed Dec 18, 2023
1 parent 1b52e6a commit 81701be
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,7 @@ public interface DatabaseDocumentationUnitRepository
"""
SELECT documentationUnit FROM DocumentationUnitDTO documentationUnit
LEFT JOIN documentationUnit.court court
WHERE (
(:documentNumberOrFileNumber IS NULL
OR (upper(documentationUnit.documentNumber) like upper(concat('%', :documentNumberOrFileNumber,'%'))
OR EXISTS (
SELECT 1
FROM FileNumberDTO fileNumber
WHERE fileNumber.documentationUnit.id = documentationUnit.id
AND upper(fileNumber.value) like upper(:documentNumberOrFileNumber)
)
OR EXISTS (
SELECT 1
FROM DeviatingFileNumberDTO deviatingFileNumber
WHERE deviatingFileNumber.documentationUnit.id = documentationUnit.id
AND deviatingFileNumber.value = :documentNumberOrFileNumber
)))
AND (:courtType IS NULL OR upper(court.type) like upper(cast(:courtType as text)))
WHERE (:courtType IS NULL OR upper(court.type) like upper(cast(:courtType as text)))
AND (:courtLocation IS NULL OR upper(court.location) like upper(cast(:courtLocation as text)))
AND (cast(:decisionDate as date) IS NULL
OR (cast(:decisionDateEnd as date) IS NULL AND documentationUnit.decisionDate = :decisionDate)
Expand All @@ -52,12 +37,129 @@ OR EXISTS (
(:status IS NOT NULL AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus = :status AND (:status IN ('PUBLISHED', 'PUBLISHING') OR documentationUnit.documentationOffice.id = :documentationOfficeId)))
)
AND (:withErrorOnly = FALSE OR documentationUnit.documentationOffice.id = :documentationOfficeId AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.withError = TRUE))
)
ORDER BY documentationUnit.documentNumber
""")
@SuppressWarnings("java:S107")
// We use JPA repository interface magic, so reducing parameter count is not possible.
Slice<DocumentationUnitSearchResultDTO> searchByDocumentUnitSearchInput(
UUID documentationOfficeId,
String courtType,
String courtLocation,
LocalDate decisionDate,
LocalDate decisionDateEnd,
PublicationStatus status,
Boolean withErrorOnly,
Boolean myDocOfficeOnly,
DocumentTypeDTO documentType,
Pageable pageable);

@Query(
value =
"""
SELECT documentationUnit FROM DocumentationUnitDTO documentationUnit
LEFT JOIN documentationUnit.court court
WHERE (upper(documentationUnit.documentNumber) like upper(concat('%', :documentNumberOrFileNumber,'%'))
AND (:courtType IS NULL OR upper(court.type) like upper(cast(:courtType as text)))
AND (:courtLocation IS NULL OR upper(court.location) like upper(cast(:courtLocation as text)))
AND (cast(:decisionDate as date) IS NULL
OR (cast(:decisionDateEnd as date) IS NULL AND documentationUnit.decisionDate = :decisionDate)
OR (cast(:decisionDateEnd as date) IS NOT NULL AND documentationUnit.decisionDate BETWEEN :decisionDate AND :decisionDateEnd))
AND (:myDocOfficeOnly = FALSE OR (:myDocOfficeOnly = TRUE AND
documentationUnit.documentationOffice.id = :documentationOfficeId))
AND (cast(:documentType as uuid) IS NULL OR documentationUnit.documentType = :documentType)
AND
(
(:status IS NULL AND ((documentationUnit.documentationOffice.id = :documentationOfficeId OR EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus IN (de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHED, de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHING)))))
OR
(:status IS NOT NULL AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus = :status AND (:status IN ('PUBLISHED', 'PUBLISHING') OR documentationUnit.documentationOffice.id = :documentationOfficeId)))
)
AND (:withErrorOnly = FALSE OR documentationUnit.documentationOffice.id = :documentationOfficeId AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.withError = TRUE))
)
ORDER BY documentationUnit.documentNumber
""")
@SuppressWarnings("java:S107")
// We use JPA repository interface magic, so reducing parameter count is not possible.
Slice<DocumentationUnitSearchResultDTO> searchByDocumentUnitSearchInputDocumentNumber(
UUID documentationOfficeId,
String documentNumberOrFileNumber,
String courtType,
String courtLocation,
LocalDate decisionDate,
LocalDate decisionDateEnd,
PublicationStatus status,
Boolean withErrorOnly,
Boolean myDocOfficeOnly,
DocumentTypeDTO documentType,
Pageable pageable);

@Query(
value =
"""
SELECT documentationUnit FROM DocumentationUnitDTO documentationUnit
LEFT JOIN documentationUnit.court court
LEFT JOIN documentationUnit.fileNumbers fileNumber
WHERE (upper(fileNumber.value) like upper(concat('%', :documentNumberOrFileNumber,'%')))
AND (:courtType IS NULL OR upper(court.type) like upper(cast(:courtType as text)))
AND (:courtLocation IS NULL OR upper(court.location) like upper(cast(:courtLocation as text)))
AND (cast(:decisionDate as date) IS NULL
OR (cast(:decisionDateEnd as date) IS NULL AND documentationUnit.decisionDate = :decisionDate)
OR (cast(:decisionDateEnd as date) IS NOT NULL AND documentationUnit.decisionDate BETWEEN :decisionDate AND :decisionDateEnd))
AND (:myDocOfficeOnly = FALSE OR (:myDocOfficeOnly = TRUE AND
documentationUnit.documentationOffice.id = :documentationOfficeId))
AND (cast(:documentType as uuid) IS NULL OR documentationUnit.documentType = :documentType)
AND
(
(:status IS NULL AND ((documentationUnit.documentationOffice.id = :documentationOfficeId OR EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus IN (de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHED, de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHING)))))
OR
(:status IS NOT NULL AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus = :status AND (:status IN ('PUBLISHED', 'PUBLISHING') OR documentationUnit.documentationOffice.id = :documentationOfficeId)))
)
AND (:withErrorOnly = FALSE OR documentationUnit.documentationOffice.id = :documentationOfficeId AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.withError = TRUE))
ORDER BY documentationUnit.documentNumber
""")
@SuppressWarnings("java:S107")
// We use JPA repository interface magic, so reducing parameter count is not possible.
Slice<DocumentationUnitSearchResultDTO> searchByDocumentUnitSearchInputFileNumber(
UUID documentationOfficeId,
String documentNumberOrFileNumber,
String courtType,
String courtLocation,
LocalDate decisionDate,
LocalDate decisionDateEnd,
PublicationStatus status,
Boolean withErrorOnly,
Boolean myDocOfficeOnly,
DocumentTypeDTO documentType,
Pageable pageable);

@Query(
value =
"""
SELECT documentationUnit FROM DocumentationUnitDTO documentationUnit
LEFT JOIN documentationUnit.court court
LEFT JOIN documentationUnit.deviatingFileNumbers fileNumber
WHERE upper(fileNumber.value) like upper(concat('%', :documentNumberOrFileNumber,'%'))
AND (:courtType IS NULL OR upper(court.type) like upper(cast(:courtType as text)))
AND (:courtLocation IS NULL OR upper(court.location) like upper(cast(:courtLocation as text)))
AND (cast(:decisionDate as date) IS NULL
OR (cast(:decisionDateEnd as date) IS NULL AND documentationUnit.decisionDate = :decisionDate)
OR (cast(:decisionDateEnd as date) IS NOT NULL AND documentationUnit.decisionDate BETWEEN :decisionDate AND :decisionDateEnd))
AND (:myDocOfficeOnly = FALSE OR (:myDocOfficeOnly = TRUE AND
documentationUnit.documentationOffice.id = :documentationOfficeId))
AND (cast(:documentType as uuid) IS NULL OR documentationUnit.documentType = :documentType)
AND
(
(:status IS NULL AND ((documentationUnit.documentationOffice.id = :documentationOfficeId OR EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus IN (de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHED, de.bund.digitalservice.ris.caselaw.domain.PublicationStatus.PUBLISHING)))))
OR
(:status IS NOT NULL AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.publicationStatus = :status AND (:status IN ('PUBLISHED', 'PUBLISHING') OR documentationUnit.documentationOffice.id = :documentationOfficeId)))
)
AND (:withErrorOnly = FALSE OR documentationUnit.documentationOffice.id = :documentationOfficeId AND EXISTS (SELECT 1 FROM StatusDTO status WHERE status.documentationUnitDTO.id = documentationUnit.id AND status.withError = TRUE))
ORDER BY documentationUnit.documentNumber
""")
@SuppressWarnings("java:S107")
// We use JPA repository interface magic, so reducing parameter count is not possible.
Slice<DocumentationUnitSearchResultDTO> searchByDocumentUnitSearchInputDeviatingFileNumber(
UUID documentationOfficeId,
String documentNumberOrFileNumber,
String courtType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,28 @@
import de.bund.digitalservice.ris.caselaw.domain.DocumentationUnitSearchInput;
import de.bund.digitalservice.ris.caselaw.domain.DocumentationUnitSearchResult;
import de.bund.digitalservice.ris.caselaw.domain.Procedure;
import de.bund.digitalservice.ris.caselaw.domain.PublicationStatus;
import de.bund.digitalservice.ris.caselaw.domain.RelatedDocumentationType;
import de.bund.digitalservice.ris.caselaw.domain.RelatedDocumentationUnit;
import de.bund.digitalservice.ris.caselaw.domain.Status;
import de.bund.digitalservice.ris.caselaw.domain.court.Court;
import de.bund.digitalservice.ris.caselaw.domain.lookuptable.documenttype.DocumentType;
import de.bund.digitalservice.ris.caselaw.domain.lookuptable.fieldoflaw.FieldOfLaw;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;
Expand Down Expand Up @@ -422,22 +428,121 @@ public Slice<RelatedDocumentationUnit> searchByRelatedDocumentationUnit(
DocumentationOfficeDTO documentationOfficeDTO =
documentationOfficeRepository.findByAbbreviation(documentationOffice.abbreviation());

Slice<DocumentationUnitSearchResultDTO> documentationUnitSearchResultDTOPage =
repository.searchByDocumentUnitSearchInput(
documentationOfficeDTO.getId(),
relatedDocumentationUnit.getFileNumber(),
List<DocumentationUnitSearchResultDTO> allResults =
getDocumentationUnitSearchResultDTOS(
pageable,
courtType,
courtLocation,
relatedDocumentationUnit.getFileNumber(),
relatedDocumentationUnit.getDecisionDate(),
null,
null,
false,
false,
DocumentTypeTransformer.transformToDTO(relatedDocumentationUnit.getDocumentType()),
pageable);
relatedDocumentationUnit.getDocumentType(),
documentationOfficeDTO);

Slice<DocumentationUnitSearchResultDTO> all =
new SliceImpl<>(
allResults.subList(
pageable.getPageNumber() * 30,
Math.min(
allResults.size(), (pageable.getPageNumber() + 1) * pageable.getPageSize())),
pageable,
allResults.size() >= (pageable.getPageNumber() + 1) * pageable.getPageSize());

return all.map(DocumentationUnitSearchResultTransformer::transformToRelatedDocumentation);
}

@NotNull
private List<DocumentationUnitSearchResultDTO> getDocumentationUnitSearchResultDTOS(
Pageable pageable,
String courtType,
String courtLocation,
String docNumberOrFileNumber,
LocalDate decisionDate,
LocalDate decisionDateEnd,
PublicationStatus status,
Boolean withError,
Boolean myDocOfficeOnly,
DocumentType documentType,
DocumentationOfficeDTO documentationOfficeDTO) {
if (docNumberOrFileNumber == null || docNumberOrFileNumber.isEmpty()) {
return repository
.searchByDocumentUnitSearchInput(
documentationOfficeDTO.getId(),
courtType,
courtLocation,
decisionDate,
decisionDateEnd,
status,
withError,
myDocOfficeOnly,
DocumentTypeTransformer.transformToDTO(documentType),
pageable)
.getContent();
}

return documentationUnitSearchResultDTOPage.map(
DocumentationUnitSearchResultTransformer::transformToRelatedDocumentation);
// FIXME we can't always start at index provided by the frontend because we cut the list
// afterwards. That's why we always reset the pageNumber to 0 to have all results for now
Pageable fixedPageRequest =
PageRequest.of(0, (pageable.getPageNumber() + 1) * pageable.getPageSize());

Slice<DocumentationUnitSearchResultDTO> docNumberResults =
repository.searchByDocumentUnitSearchInputDocumentNumber(
documentationOfficeDTO.getId(),
docNumberOrFileNumber,
courtType,
courtLocation,
decisionDate,
decisionDateEnd,
status,
withError,
myDocOfficeOnly,
DocumentTypeTransformer.transformToDTO(documentType),
fixedPageRequest);

Slice<DocumentationUnitSearchResultDTO> fileNumberResults =
repository.searchByDocumentUnitSearchInputFileNumber(
documentationOfficeDTO.getId(),
docNumberOrFileNumber,
courtType,
courtLocation,
decisionDate,
decisionDateEnd,
status,
withError,
myDocOfficeOnly,
DocumentTypeTransformer.transformToDTO(documentType),
fixedPageRequest);

Slice<DocumentationUnitSearchResultDTO> deviatingFileNumberResults =
repository.searchByDocumentUnitSearchInputDeviatingFileNumber(
documentationOfficeDTO.getId(),
docNumberOrFileNumber,
courtType,
courtLocation,
decisionDate,
decisionDateEnd,
status,
withError,
myDocOfficeOnly,
DocumentTypeTransformer.transformToDTO(documentType),
fixedPageRequest);
List<DocumentationUnitSearchResultDTO> allResults = new ArrayList<>();
allResults.addAll(docNumberResults.getContent());
allResults.addAll(fileNumberResults.getContent());
allResults.addAll(deviatingFileNumberResults.getContent());

return allResults.stream()
.sorted(
(o1, o2) -> {
if (o1.getDocumentNumber() != null && o2.getDocumentNumber() != null) {
return o1.getDocumentNumber().compareTo(o2.getDocumentNumber());
}
return 0;
})
.toList();
}

@Transactional(transactionManager = "jpaTransactionManager")
Expand All @@ -455,22 +560,31 @@ public Slice<DocumentationUnitSearchResult> searchByDocumentationUnitSearchInput
Boolean withError =
Optional.ofNullable(searchInput.status()).map(Status::withError).orElse(false);

Slice<DocumentationUnitSearchResultDTO> documentationUnitSearchResultDTOPage =
repository.searchByDocumentUnitSearchInput(
documentationOfficeDTO.getId(),
searchInput.documentNumberOrFileNumber(),
List<DocumentationUnitSearchResultDTO> allResults =
getDocumentationUnitSearchResultDTOS(
pageable,
searchInput.courtType(),
searchInput.courtLocation(),
searchInput.documentNumberOrFileNumber(),
searchInput.decisionDate(),
searchInput.decisionDateEnd(),
searchInput.status() != null ? searchInput.status().publicationStatus() : null,
withError,
searchInput.myDocOfficeOnly(),
null,
pageable);

return documentationUnitSearchResultDTOPage.map(
DocumentationUnitSearchResultTransformer::transformToDomain);
documentationOfficeDTO);

// FIXME in case we by chance only have exactly <pageSize> results, we still get hasNext = true
Slice<DocumentationUnitSearchResultDTO> all =
new SliceImpl<>(
allResults.subList(
pageable.getPageNumber() * 30,
Math.min(
allResults.size(), (pageable.getPageNumber() + 1) * pageable.getPageSize())),
pageable,
allResults.size() >= (pageable.getPageNumber() + 1) * pageable.getPageSize());

return all.map(DocumentationUnitSearchResultTransformer::transformToDomain);
}

@Override
Expand Down
5 changes: 2 additions & 3 deletions backend/src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ mail:
password: pa55word
#logging:
# level:
# org.springframework: DEBUG
# org.hibernate.SQL: DEBUG
# org.hibernate.type.descriptor.sql.BasicBinder: TRACE
# sql: debug
# org.hibernate.orm.jdbc.bind: trace

Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,12 @@ CREATE INDEX

CREATE INDEX
status_documentation_unit_id_idx ON incremental_migration.status USING btree (documentation_unit_id);

CREATE INDEX
file_number_value_upper_trgm_idx ON incremental_migration.file_number USING gin (UPPER(value::text) gin_trgm_ops);

CREATE INDEX
deviating_file_number_value_upper_trgm_idx ON incremental_migration.deviating_file_number USING gin (UPPER(value::text) gin_trgm_ops);

CREATE INDEX
documentation_unit_document_number_upper_trgm_idx ON incremental_migration.documentation_unit USING gin (UPPER(document_number::text) gin_trgm_ops);

0 comments on commit 81701be

Please sign in to comment.