perf: strip unused fields from book list API response (#2741)

* perf: strip unused fields from book list API response

* fix: regenerate package-lock.json to sync with package.json
This commit is contained in:
ACX
2026-02-13 22:09:01 -07:00
committed by GitHub
parent 77b4deb942
commit ffd2adb032
5 changed files with 650 additions and 10 deletions

View File

@@ -70,6 +70,8 @@ public class BookMetadata {
private List<BookReview> bookReviews;
private Double rating;
private Boolean allMetadataLocked;
private Boolean titleLocked;
private Boolean subtitleLocked;
private Boolean publisherLocked;

View File

@@ -2,6 +2,8 @@ package org.booklore.service.book;
import org.booklore.mapper.v2.BookMapperV2;
import org.booklore.model.dto.Book;
import org.booklore.model.dto.BookMetadata;
import org.booklore.model.dto.ComicMetadata;
import org.booklore.model.entity.BookEntity;
import org.booklore.repository.BookRepository;
import org.booklore.service.restriction.ContentRestrictionService;
@@ -22,13 +24,13 @@ public class BookQueryService {
public List<Book> getAllBooks(boolean includeDescription) {
List<BookEntity> books = bookRepository.findAllWithMetadata();
return mapBooksToDto(books, includeDescription, null);
return mapBooksToDto(books, includeDescription, null, !includeDescription);
}
public List<Book> getAllBooksByLibraryIds(Set<Long> libraryIds, boolean includeDescription, Long userId) {
List<BookEntity> books = bookRepository.findAllWithMetadataByLibraryIds(libraryIds);
books = contentRestrictionService.applyRestrictions(books, userId);
return mapBooksToDto(books, includeDescription, userId);
return mapBooksToDto(books, includeDescription, userId, !includeDescription);
}
public List<BookEntity> findAllWithMetadataByIds(Set<Long> bookIds) {
@@ -43,13 +45,13 @@ public class BookQueryService {
bookRepository.saveAll(books);
}
private List<Book> mapBooksToDto(List<BookEntity> books, boolean includeDescription, Long userId) {
private List<Book> mapBooksToDto(List<BookEntity> books, boolean includeDescription, Long userId, boolean stripForListView) {
return books.stream()
.map(book -> mapBookToDto(book, includeDescription, userId))
.map(book -> mapBookToDto(book, includeDescription, userId, stripForListView))
.collect(Collectors.toList());
}
private Book mapBookToDto(BookEntity bookEntity, boolean includeDescription, Long userId) {
private Book mapBookToDto(BookEntity bookEntity, boolean includeDescription, Long userId, boolean stripForListView) {
Book dto = bookMapperV2.toDTO(bookEntity);
if (!includeDescription && dto.getMetadata() != null) {
@@ -62,6 +64,175 @@ public class BookQueryService {
.collect(Collectors.toSet()));
}
if (stripForListView) {
stripFieldsForListView(dto);
}
return dto;
}
private void stripFieldsForListView(Book dto) {
dto.setLibraryPath(null);
BookMetadata m = dto.getMetadata();
if (m != null) {
// Compute allMetadataLocked before stripping lock flags
m.setAllMetadataLocked(computeAllMetadataLocked(m));
// Strip lock flags
m.setTitleLocked(null);
m.setSubtitleLocked(null);
m.setPublisherLocked(null);
m.setPublishedDateLocked(null);
m.setDescriptionLocked(null);
m.setSeriesNameLocked(null);
m.setSeriesNumberLocked(null);
m.setSeriesTotalLocked(null);
m.setIsbn13Locked(null);
m.setIsbn10Locked(null);
m.setAsinLocked(null);
m.setGoodreadsIdLocked(null);
m.setComicvineIdLocked(null);
m.setHardcoverIdLocked(null);
m.setHardcoverBookIdLocked(null);
m.setDoubanIdLocked(null);
m.setGoogleIdLocked(null);
m.setPageCountLocked(null);
m.setLanguageLocked(null);
m.setAmazonRatingLocked(null);
m.setAmazonReviewCountLocked(null);
m.setGoodreadsRatingLocked(null);
m.setGoodreadsReviewCountLocked(null);
m.setHardcoverRatingLocked(null);
m.setHardcoverReviewCountLocked(null);
m.setDoubanRatingLocked(null);
m.setDoubanReviewCountLocked(null);
m.setLubimyczytacIdLocked(null);
m.setLubimyczytacRatingLocked(null);
m.setRanobedbIdLocked(null);
m.setRanobedbRatingLocked(null);
m.setAudibleIdLocked(null);
m.setAudibleRatingLocked(null);
m.setAudibleReviewCountLocked(null);
m.setExternalUrlLocked(null);
m.setCoverLocked(null);
m.setAudiobookCoverLocked(null);
m.setAuthorsLocked(null);
m.setCategoriesLocked(null);
m.setMoodsLocked(null);
m.setTagsLocked(null);
m.setReviewsLocked(null);
m.setNarratorLocked(null);
m.setAbridgedLocked(null);
m.setAgeRatingLocked(null);
m.setContentRatingLocked(null);
// Strip external IDs
m.setAsin(null);
m.setGoodreadsId(null);
m.setComicvineId(null);
m.setHardcoverId(null);
m.setHardcoverBookId(null);
m.setGoogleId(null);
m.setLubimyczytacId(null);
m.setRanobedbId(null);
m.setAudibleId(null);
m.setDoubanId(null);
// Strip unused detail fields
m.setSubtitle(null);
m.setSeriesTotal(null);
m.setAbridged(null);
m.setExternalUrl(null);
m.setThumbnailUrl(null);
m.setProvider(null);
m.setAudiobookMetadata(null);
m.setBookReviews(null);
// Strip unused ratings
m.setDoubanRating(null);
m.setDoubanReviewCount(null);
m.setAudibleRating(null);
m.setAudibleReviewCount(null);
m.setLubimyczytacRating(null);
// Strip ComicMetadata fields
ComicMetadata cm = m.getComicMetadata();
if (cm != null) {
// Strip comic lock flags
cm.setIssueNumberLocked(null);
cm.setVolumeNameLocked(null);
cm.setVolumeNumberLocked(null);
cm.setStoryArcLocked(null);
cm.setStoryArcNumberLocked(null);
cm.setAlternateSeriesLocked(null);
cm.setAlternateIssueLocked(null);
cm.setImprintLocked(null);
cm.setFormatLocked(null);
cm.setBlackAndWhiteLocked(null);
cm.setMangaLocked(null);
cm.setReadingDirectionLocked(null);
cm.setWebLinkLocked(null);
cm.setNotesLocked(null);
cm.setCreatorsLocked(null);
cm.setPencillersLocked(null);
cm.setInkersLocked(null);
cm.setColoristsLocked(null);
cm.setLetterersLocked(null);
cm.setCoverArtistsLocked(null);
cm.setEditorsLocked(null);
cm.setCharactersLocked(null);
cm.setTeamsLocked(null);
cm.setLocationsLocked(null);
// Strip non-filter detail fields
cm.setIssueNumber(null);
cm.setVolumeName(null);
cm.setVolumeNumber(null);
cm.setStoryArc(null);
cm.setStoryArcNumber(null);
cm.setAlternateSeries(null);
cm.setAlternateIssue(null);
cm.setImprint(null);
cm.setFormat(null);
cm.setBlackAndWhite(null);
cm.setManga(null);
cm.setReadingDirection(null);
cm.setWebLink(null);
cm.setNotes(null);
}
}
}
private boolean computeAllMetadataLocked(BookMetadata m) {
Boolean[] bookLocks = {
m.getTitleLocked(), m.getSubtitleLocked(), m.getPublisherLocked(),
m.getPublishedDateLocked(), m.getDescriptionLocked(), m.getSeriesNameLocked(),
m.getSeriesNumberLocked(), m.getSeriesTotalLocked(), m.getIsbn13Locked(),
m.getIsbn10Locked(), m.getAsinLocked(), m.getGoodreadsIdLocked(),
m.getComicvineIdLocked(), m.getHardcoverIdLocked(), m.getHardcoverBookIdLocked(),
m.getDoubanIdLocked(), m.getGoogleIdLocked(), m.getPageCountLocked(),
m.getLanguageLocked(), m.getAmazonRatingLocked(), m.getAmazonReviewCountLocked(),
m.getGoodreadsRatingLocked(), m.getGoodreadsReviewCountLocked(),
m.getHardcoverRatingLocked(), m.getHardcoverReviewCountLocked(),
m.getDoubanRatingLocked(), m.getDoubanReviewCountLocked(),
m.getLubimyczytacIdLocked(), m.getLubimyczytacRatingLocked(),
m.getRanobedbIdLocked(), m.getRanobedbRatingLocked(),
m.getAudibleIdLocked(), m.getAudibleRatingLocked(), m.getAudibleReviewCountLocked(),
m.getExternalUrlLocked(), m.getCoverLocked(), m.getAudiobookCoverLocked(),
m.getAuthorsLocked(), m.getCategoriesLocked(), m.getMoodsLocked(),
m.getTagsLocked(), m.getReviewsLocked(), m.getNarratorLocked(),
m.getAbridgedLocked(), m.getAgeRatingLocked(), m.getContentRatingLocked()
};
boolean hasAnyLock = false;
for (Boolean lock : bookLocks) {
if (Boolean.TRUE.equals(lock)) {
hasAnyLock = true;
} else {
return false;
}
}
return hasAnyLock;
}
}