Skip to content

Commit

Permalink
Merge pull request #2677 from dbmdz/speedup-wmid-downwards
Browse files Browse the repository at this point in the history
Speedup wmid downwards
  • Loading branch information
daforster authored Nov 15, 2023
2 parents 08a2fa4 + b98f45e commit deada20
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import de.digitalcollections.model.identifiable.entity.Collection;
import de.digitalcollections.model.identifiable.entity.Project;
import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.resource.FileResource;
import de.digitalcollections.model.identifiable.resource.ImageFileResource;
import de.digitalcollections.model.list.paging.PageRequest;
Expand Down Expand Up @@ -68,6 +69,17 @@ default PageResponse<Project> findProjects(DigitalObject digitalObject, PageRequ
PageResponse<Project> findProjects(UUID digitalObjectUuid, PageRequest pageRequest)
throws RepositoryException;

default PageResponse<DigitalObject> findDigitalObjectsByItem(Item item, PageRequest pageRequest)
throws RepositoryException {
if (item == null) {
throw new IllegalArgumentException("find failed: given object must not be null");
}
return findDigitalObjectsByItem(item.getUuid(), pageRequest);
}

PageResponse<DigitalObject> findDigitalObjectsByItem(UUID itemUuid, PageRequest pageRequest)
throws RepositoryException;

default List<FileResource> getFileResources(DigitalObject digitalObject)
throws RepositoryException {
if (digitalObject == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import de.digitalcollections.cudami.server.backend.api.repository.exceptions.RepositoryException;
import de.digitalcollections.cudami.server.backend.api.repository.identifiable.entity.EntityRepository;
import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
import de.digitalcollections.model.list.paging.PageRequest;
Expand All @@ -14,17 +13,6 @@
/** Repository for Item persistence handling. */
public interface ItemRepository extends EntityRepository<Item> {

default PageResponse<DigitalObject> findDigitalObjects(Item item, PageRequest pageRequest)
throws RepositoryException {
if (item == null) {
throw new IllegalArgumentException("find failed: given object must not be null");
}
return findDigitalObjects(item.getUuid(), pageRequest);
}

PageResponse<DigitalObject> findDigitalObjects(UUID itemUuid, PageRequest pageRequest)
throws RepositoryException;

default PageResponse<Item> findItemsByManifestation(
Manifestation manifestation, PageRequest pageRequest) throws RepositoryException {
if (manifestation == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,38 @@ public PageResponse<Project> findProjects(UUID digitalObjectUuid, PageRequest pa
return new PageResponse<>(result, pageRequest, total);
}

@Override
public PageResponse<DigitalObject> findDigitalObjectsByItem(
UUID itemUuid, PageRequest pageRequest) throws RepositoryException {
StringBuilder commonSql =
new StringBuilder(
" FROM "
+ tableName
+ " "
+ tableAlias
+ " WHERE "
+ tableAlias
+ ".item_uuid = :uuid");
Map<String, Object> argumentMappings = new HashMap<>();
argumentMappings.put("uuid", itemUuid);

addFiltering(pageRequest, commonSql, argumentMappings);

StringBuilder innerQuery = new StringBuilder("SELECT * " + commonSql);
addPagingAndSorting(pageRequest, innerQuery);
List<DigitalObject> result =
retrieveList(
getSqlSelectReducedFields(),
innerQuery,
argumentMappings,
getOrderBy(pageRequest.getSorting()));

StringBuilder countQuery = new StringBuilder("SELECT count(*)" + commonSql);
long total = retrieveCount(countQuery, argumentMappings);

return new PageResponse<>(result, pageRequest, total);
}

@Override
public String getColumnName(String modelProperty) {
if (modelProperty == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
import de.digitalcollections.model.identifiable.entity.agent.CorporateBody;
import de.digitalcollections.model.identifiable.entity.agent.Family;
import de.digitalcollections.model.identifiable.entity.agent.Person;
import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
import de.digitalcollections.model.list.filtering.Filtering;
import de.digitalcollections.model.list.paging.PageRequest;
import de.digitalcollections.model.list.paging.PageResponse;
import de.digitalcollections.model.text.LocalizedText;
Expand Down Expand Up @@ -140,69 +138,21 @@ protected void basicReduceRowsBiConsumer(Map<UUID, Item> map, RowView rowView) {
}
}

@Override
public PageResponse<DigitalObject> findDigitalObjects(UUID itemUuid, PageRequest pageRequest)
throws RepositoryException {
final String doTableAlias = digitalObjectRepositoryImpl.getTableAlias();
final String doTableName = digitalObjectRepositoryImpl.getTableName();

StringBuilder commonSql =
new StringBuilder(
" FROM "
+ doTableName
+ " AS "
+ doTableAlias
+ " WHERE "
+ doTableAlias
+ ".item_uuid = :uuid");
Map<String, Object> argumentMappings = new HashMap<>();
argumentMappings.put("uuid", itemUuid);

Filtering filtering = pageRequest.getFiltering();
// as filtering has other target object type (digitalobject) than this
// repository (item)
// we have to rename filter field names to target table alias and column names:
mapFilterExpressionsToOtherTableColumnNames(filtering, digitalObjectRepositoryImpl);
addFiltering(pageRequest, commonSql, argumentMappings);

StringBuilder innerQuery = new StringBuilder("SELECT * " + commonSql);
digitalObjectRepositoryImpl.addPagingAndSorting(pageRequest, innerQuery);
List<DigitalObject> result =
digitalObjectRepositoryImpl.retrieveList(
digitalObjectRepositoryImpl.getSqlSelectReducedFields(),
innerQuery,
argumentMappings,
getOrderBy(pageRequest.getSorting()));

StringBuilder countQuery = new StringBuilder("SELECT count(*)" + commonSql);
long total = retrieveCount(countQuery, argumentMappings);

return new PageResponse<>(result, pageRequest, total);
}

@Override
public PageResponse<Item> findItemsByManifestation(
UUID manifestationUuid, PageRequest pageRequest) throws RepositoryException {
final String itemTableAlias = getTableAlias();
final String itemTableName = getTableName();

StringBuilder commonSql =
new StringBuilder(
" FROM "
+ itemTableName
+ " AS "
+ itemTableAlias
+ tableName
+ " "
+ tableAlias
+ " WHERE "
+ itemTableAlias
+ tableAlias
+ ".manifestation = :uuid");
Map<String, Object> argumentMappings = new HashMap<>();
argumentMappings.put("uuid", manifestationUuid);

Filtering filtering = pageRequest.getFiltering();
// as filtering has other target object type (item) than this repository
// (manifestation)
// we have to rename filter field names to target table alias and column names:
mapFilterExpressionsToOtherTableColumnNames(filtering, this);
addFiltering(pageRequest, commonSql, argumentMappings);

StringBuilder innerQuery = new StringBuilder("SELECT * " + commonSql);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,26 +317,26 @@ public PageResponse<Manifestation> findManifestationsByWork(
@Override
public PageResponse<Manifestation> findSubParts(UUID uuid, PageRequest pageRequest)
throws RepositoryException {
final String doTableName = "manifestation_manifestations";
final String doTableAlias = "mms";
final String xtable = "manifestation_manifestations";
final String xtableAlias = "mms";

StringBuilder commonSql =
new StringBuilder(
" FROM "
+ doTableName
+ " AS "
+ doTableAlias
+ xtable
+ " "
+ xtableAlias
+ " INNER JOIN "
+ tableName
+ " "
+ tableAlias
+ " ON "
+ doTableAlias
+ xtableAlias
+ ".object_uuid = "
+ tableAlias
+ ".uuid"
+ " WHERE "
+ doTableAlias
+ xtableAlias
+ ".subject_uuid = :subject_uuid");

Map<String, Object> argumentMappings = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CREATE INDEX IF NOT EXISTS idx_digitalobjects_item_hash on digitalobjects using hash (item_uuid);
CREATE INDEX IF NOT EXISTS idx_items_manifestation_hash on items using hash (manifestation);

Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,74 @@ void update() throws RepositoryException {
assertThat(digitalObject).isEqualToComparingFieldByField(persisted);
}

@Test
@DisplayName("can return an empty set of connected digital objects for an null item")
void digitalObjectsForNullItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
assertThat(repo.findDigitalObjectsByItem((UUID) null, pageRequest)).isEmpty();
}

@Test
@DisplayName("can return an empty set of connected digital objects for an nonexisting item")
void digitalObjectsForNonexistingItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
assertThat(repo.findDigitalObjectsByItem(UUID.randomUUID(), pageRequest)).isEmpty();
}

@Test
@DisplayName(
"can return an empty set of connected digital objects for an item which has no digital objects connected to it")
void digitalObjectsForItemWithoutDigitalObjects() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
Item item = Item.builder().label("item without digital objects").build();
itemRepository.save(item);
DigitalObject digitalObject =
DigitalObject.builder().label("digital object without item").build();
repo.save(digitalObject);

assertThat(repo.findDigitalObjectsByItem(item.getUuid(), pageRequest)).isEmpty();
}

@Test
@DisplayName("can return digital objects connected to an item")
void digitalObjectsForItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
Item item1 = Item.builder().label("item1 with two digitalObject2").build();
itemRepository.save(item1);
Item item2 = Item.builder().label("item2 with one digitalObject").build();
itemRepository.save(item2);
DigitalObject digitalObject1 =
DigitalObject.builder().label("digital object 1 for item1").item(item1).build();
repo.save(digitalObject1);
DigitalObject digitalObject2 =
DigitalObject.builder().label("digital object 2 for item1").item(item1).build();
repo.save(digitalObject2);
DigitalObject digitalObject3 =
DigitalObject.builder().label("digital object 1 for item2").item(item2).build();
repo.save(digitalObject3);

PageResponse<DigitalObject> actual =
repo.findDigitalObjectsByItem(item1.getUuid(), pageRequest);
assertThat(actual.getContent()).containsExactlyInAnyOrder(digitalObject1, digitalObject2);
}

@Test
@DisplayName("can use paging on retrieval of digital objects connected to an item")
void pagedDigitalObjectsForItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(1).pageNumber(0).build();
Item item = Item.builder().label("item1 with two digitalObject2").build();
itemRepository.save(item);
DigitalObject digitalObject1 =
DigitalObject.builder().label("digital object 1 for item1").item(item).build();
repo.save(digitalObject1);
DigitalObject digitalObject2 =
DigitalObject.builder().label("digital object 2 for item1").item(item).build();
repo.save(digitalObject2);

PageResponse<DigitalObject> actual = repo.findDigitalObjectsByItem(item.getUuid(), pageRequest);
assertThat(actual.getContent()).hasSize(1);
}

// -----------------------------------------------------------------
private void ensureLicense(License license) throws RepositoryException {
if (licenseRepository.getByUuid(license.getUuid()) == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import de.digitalcollections.model.identifiable.entity.agent.CorporateBody;
import de.digitalcollections.model.identifiable.entity.agent.Gender;
import de.digitalcollections.model.identifiable.entity.agent.Person;
import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
import de.digitalcollections.model.list.filtering.FilterCriterion;
Expand Down Expand Up @@ -368,73 +367,6 @@ void testIsPartOfFiltering() throws RepositoryException {
assertThat(actualItem).isEqualTo(expectedItem);
}

@Test
@DisplayName("can return an empty set of connected digital objects for an null item")
void digitalObjectsForNullItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
assertThat(repo.findDigitalObjects((UUID) null, pageRequest)).isEmpty();
}

@Test
@DisplayName("can return an empty set of connected digital objects for an nonexisting item")
void digitalObjectsForNonexistingItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
assertThat(repo.findDigitalObjects(UUID.randomUUID(), pageRequest)).isEmpty();
}

@Test
@DisplayName(
"can return an empty set of connected digital objects for an item which has no digital objects connected to it")
void digitalObjectsForItemWithoutDigitalObjects() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
Item item = Item.builder().label("item without digital objects").build();
repo.save(item);
DigitalObject digitalObject =
DigitalObject.builder().label("digital object without item").build();
digitalObjectRepository.save(digitalObject);

assertThat(repo.findDigitalObjects(item.getUuid(), pageRequest)).isEmpty();
}

@Test
@DisplayName("can return digital objects connected to an item")
void digitalObjectsForItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(25).pageNumber(0).build();
Item item1 = Item.builder().label("item1 with two digitalObject2").build();
repo.save(item1);
Item item2 = Item.builder().label("item2 with one digitalObject").build();
repo.save(item2);
DigitalObject digitalObject1 =
DigitalObject.builder().label("digital object 1 for item1").item(item1).build();
digitalObjectRepository.save(digitalObject1);
DigitalObject digitalObject2 =
DigitalObject.builder().label("digital object 2 for item1").item(item1).build();
digitalObjectRepository.save(digitalObject2);
DigitalObject digitalObject3 =
DigitalObject.builder().label("digital object 1 for item2").item(item2).build();
digitalObjectRepository.save(digitalObject3);

PageResponse<DigitalObject> actual = repo.findDigitalObjects(item1.getUuid(), pageRequest);
assertThat(actual.getContent()).containsExactlyInAnyOrder(digitalObject1, digitalObject2);
}

@Test
@DisplayName("can use paging on retrieval of digital objects connected to an item")
void pagedDigitalObjectsForItem() throws RepositoryException {
PageRequest pageRequest = PageRequest.builder().pageSize(1).pageNumber(0).build();
Item item = Item.builder().label("item1 with two digitalObject2").build();
repo.save(item);
DigitalObject digitalObject1 =
DigitalObject.builder().label("digital object 1 for item1").item(item).build();
digitalObjectRepository.save(digitalObject1);
DigitalObject digitalObject2 =
DigitalObject.builder().label("digital object 2 for item1").item(item).build();
digitalObjectRepository.save(digitalObject2);

PageResponse<DigitalObject> actual = repo.findDigitalObjects(item.getUuid(), pageRequest);
assertThat(actual.getContent()).hasSize(1);
}

@DisplayName("can retrieve items for a manifestation")
@Test
public void retrieveItems() throws RepositoryException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ PageResponse<Collection> findCollections(DigitalObject digitalObject, PageReques
PageResponse<Project> findProjects(DigitalObject digitalObject, PageRequest pageRequest)
throws ServiceException;

PageResponse<DigitalObject> findDigitalObjectsByItem(Item item, PageRequest pageRequest)
throws ServiceException;

@Override
default DigitalObject getByExample(DigitalObject digitalObject) throws ServiceException {
return getByExample(digitalObject, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import de.digitalcollections.cudami.server.business.api.service.exceptions.ServiceException;
import de.digitalcollections.cudami.server.business.api.service.identifiable.entity.EntityService;
import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
import de.digitalcollections.model.list.paging.PageRequest;
Expand All @@ -12,9 +11,6 @@

public interface ItemService extends EntityService<Item> {

PageResponse<DigitalObject> findDigitalObjects(Item item, PageRequest pageRequest)
throws ServiceException;

PageResponse<Item> findItemsByManifestation(Manifestation manifestation, PageRequest pageRequest)
throws ServiceException;

Expand Down
Loading

0 comments on commit deada20

Please sign in to comment.