feat(api): count series by first letter

This commit is contained in:
Gauthier Roebroeck 2021-07-21 11:06:25 +08:00
parent 1fe55809a1
commit 199c6190a3
4 changed files with 86 additions and 0 deletions

View file

@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.SeriesSearchWithReadProgress
import org.gotson.komga.infrastructure.web.toFilePath
import org.gotson.komga.interfaces.rest.dto.AuthorDto
import org.gotson.komga.interfaces.rest.dto.BookMetadataAggregationDto
import org.gotson.komga.interfaces.rest.dto.GroupCountDto
import org.gotson.komga.interfaces.rest.dto.SeriesDto
import org.gotson.komga.interfaces.rest.dto.SeriesMetadataDto
import org.gotson.komga.interfaces.rest.persistence.SeriesDtoRepository
@ -20,7 +21,9 @@ import org.jooq.Record
import org.jooq.ResultQuery
import org.jooq.SelectOnConditionStep
import org.jooq.impl.DSL
import org.jooq.impl.DSL.count
import org.jooq.impl.DSL.lower
import org.jooq.impl.DSL.substring
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.PageRequest
@ -103,6 +106,27 @@ class SeriesDtoDao(
return findAll(conditions, userId, pageable, search.toJoinConditions())
}
override fun countByFirstCharacter(search: SeriesSearchWithReadProgress, userId: String): List<GroupCountDto> {
val conditions = search.toCondition()
val joinConditions = search.toJoinConditions()
val firstChar = lower(substring(d.TITLE_SORT, 1, 1))
return dsl.select(firstChar, count())
.from(s)
.leftJoin(d).on(s.ID.eq(d.SERIES_ID))
.leftJoin(bma).on(s.ID.eq(bma.SERIES_ID))
.leftJoin(rs).on(s.ID.eq(rs.SERIES_ID)).and(readProgressConditionSeries(userId))
.apply { if (joinConditions.genre) leftJoin(g).on(s.ID.eq(g.SERIES_ID)) }
.apply { if (joinConditions.tag) leftJoin(st).on(s.ID.eq(st.SERIES_ID)) }
.apply { if (joinConditions.collection) leftJoin(cs).on(s.ID.eq(cs.SERIES_ID)) }
.apply { if (joinConditions.aggregationAuthor) leftJoin(bmaa).on(s.ID.eq(bmaa.SERIES_ID)) }
.where(conditions)
.groupBy(firstChar)
.map {
GroupCountDto(it.value1(), it.value2())
}
}
override fun findByIdOrNull(seriesId: String, userId: String): SeriesDto? =
selectBase(userId)
.where(s.ID.eq(seriesId))

View file

@ -39,6 +39,7 @@ import org.gotson.komga.infrastructure.web.Authors
import org.gotson.komga.infrastructure.web.DelimitedPair
import org.gotson.komga.interfaces.rest.dto.BookDto
import org.gotson.komga.interfaces.rest.dto.CollectionDto
import org.gotson.komga.interfaces.rest.dto.GroupCountDto
import org.gotson.komga.interfaces.rest.dto.SeriesDto
import org.gotson.komga.interfaces.rest.dto.SeriesMetadataUpdateDto
import org.gotson.komga.interfaces.rest.dto.TachiyomiReadProgressDto
@ -162,6 +163,58 @@ class SeriesController(
.map { it.restrictUrl(!principal.user.roleAdmin) }
}
@AuthorsAsQueryParam
@Parameters(
Parameter(
description = "Search by regex criteria, in the form: regex,field. Supported fields are TITLE and TITLE_SORT.",
`in` = ParameterIn.QUERY, name = "search_regex", schema = Schema(type = "string")
)
)
@GetMapping("alphabetical-groups")
fun getAlphabeticalGroups(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "search", required = false) searchTerm: String?,
@Parameter(hidden = true) @DelimitedPair("search_regex") searchRegex: Pair<String, String>?,
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
@RequestParam(name = "collection_id", required = false) collectionIds: List<String>?,
@RequestParam(name = "status", required = false) metadataStatus: List<SeriesMetadata.Status>?,
@RequestParam(name = "read_status", required = false) readStatus: List<ReadStatus>?,
@RequestParam(name = "publisher", required = false) publishers: List<String>?,
@RequestParam(name = "language", required = false) languages: List<String>?,
@RequestParam(name = "genre", required = false) genres: List<String>?,
@RequestParam(name = "tag", required = false) tags: List<String>?,
@RequestParam(name = "age_rating", required = false) ageRatings: List<String>?,
@RequestParam(name = "release_year", required = false) release_years: List<String>?,
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
@Parameter(hidden = true) @Authors authors: List<Author>?,
@Parameter(hidden = true) page: Pageable
): List<GroupCountDto> {
val seriesSearch = SeriesSearchWithReadProgress(
libraryIds = principal.user.getAuthorizedLibraryIds(libraryIds),
collectionIds = collectionIds,
searchTerm = searchTerm,
searchRegex = searchRegex?.let {
when (it.second.lowercase()) {
"title" -> Pair(it.first, SeriesSearch.SearchField.TITLE)
"title_sort" -> Pair(it.first, SeriesSearch.SearchField.TITLE_SORT)
else -> null
}
},
metadataStatus = metadataStatus,
readStatus = readStatus,
publishers = publishers,
deleted = deleted,
languages = languages,
genres = genres,
tags = tags,
ageRatings = ageRatings?.map { it.toIntOrNull() },
releaseYears = release_years,
authors = authors
)
return seriesDtoRepository.countByFirstCharacter(seriesSearch, principal.user.id)
}
@Operation(description = "Return recently added or updated series.")
@PageableWithoutSortAsQueryParam
@GetMapping("/latest")

View file

@ -0,0 +1,6 @@
package org.gotson.komga.interfaces.rest.dto
data class GroupCountDto(
val group: String,
val count: Int,
)

View file

@ -1,6 +1,7 @@
package org.gotson.komga.interfaces.rest.persistence
import org.gotson.komga.domain.model.SeriesSearchWithReadProgress
import org.gotson.komga.interfaces.rest.dto.GroupCountDto
import org.gotson.komga.interfaces.rest.dto.SeriesDto
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
@ -11,4 +12,6 @@ interface SeriesDtoRepository {
fun findAll(search: SeriesSearchWithReadProgress, userId: String, pageable: Pageable): Page<SeriesDto>
fun findAllByCollectionId(collectionId: String, search: SeriesSearchWithReadProgress, userId: String, pageable: Pageable): Page<SeriesDto>
fun findAllRecentlyUpdated(search: SeriesSearchWithReadProgress, userId: String, pageable: Pageable): Page<SeriesDto>
fun countByFirstCharacter(search: SeriesSearchWithReadProgress, userId: String): List<GroupCountDto>
}