Send last read chapter in Mangas in Category API (#507)

* Send last read chapter with manga

* optimize query

* introduce new field for better performance
This commit is contained in:
akabhirav
2023-02-21 04:47:45 +05:30
committed by GitHub
parent ac99dd55a2
commit 783787e514
2 changed files with 31 additions and 34 deletions

View File

@@ -10,14 +10,16 @@ package suwayomi.tachidesk.manga.impl
import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.alias
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.count import org.jetbrains.exposed.sql.count
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.leftJoin
import org.jetbrains.exposed.sql.max
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import org.jetbrains.exposed.sql.wrapAsExpression
import suwayomi.tachidesk.manga.impl.Category.DEFAULT_CATEGORY_ID import suwayomi.tachidesk.manga.impl.Category.DEFAULT_CATEGORY_ID
import suwayomi.tachidesk.manga.impl.util.lang.isEmpty import suwayomi.tachidesk.manga.impl.util.lang.isEmpty
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
@@ -61,46 +63,40 @@ object CategoryManga {
* list of mangas that belong to a category * list of mangas that belong to a category
*/ */
fun getCategoryMangaList(categoryId: Int): List<MangaDataClass> { fun getCategoryMangaList(categoryId: Int): List<MangaDataClass> {
val unreadExpression = wrapAsExpression<Long>( // Select the required columns from the MangaTable and add the aggregate functions to compute unread, download, and chapter counts
ChapterTable val unreadCountEx = ChapterTable.isRead.count().alias("unread_count")
.slice(ChapterTable.id.count()) val downloadedCount = ChapterTable.isDownloaded.count().alias("download_count")
.select { (MangaTable.id eq ChapterTable.manga) and (ChapterTable.isRead eq false) } val chapterCount = ChapterTable.id.count().alias("chapter_count")
) val lastReadAt = ChapterTable.lastReadAt.max().alias("last_read_at")
val downloadExpression = wrapAsExpression<Long>( val selectedColumns = MangaTable.columns + unreadCountEx + downloadedCount + chapterCount + lastReadAt
ChapterTable
.slice(ChapterTable.id.count())
.select { (MangaTable.id eq ChapterTable.manga) and (ChapterTable.isDownloaded eq true) }
)
val chapterCountExpression = wrapAsExpression<Long>(
ChapterTable
.slice(ChapterTable.id.count())
.select { (MangaTable.id eq ChapterTable.manga) }
)
val selectedColumns = MangaTable.columns + unreadExpression + downloadExpression + chapterCountExpression
val transform: (ResultRow) -> MangaDataClass = { val transform: (ResultRow) -> MangaDataClass = {
// Map the data from the result row to the MangaDataClass
val dataClass = MangaTable.toDataClass(it) val dataClass = MangaTable.toDataClass(it)
dataClass.unreadCount = it[unreadExpression] dataClass.lastReadAt = it[lastReadAt]
dataClass.downloadCount = it[downloadExpression] dataClass.unreadCount = it[unreadCountEx]
dataClass.chapterCount = it[chapterCountExpression] dataClass.downloadCount = it[downloadedCount]
dataClass.chapterCount = it[chapterCount]
dataClass dataClass
} }
if (categoryId == DEFAULT_CATEGORY_ID) {
return transaction {
MangaTable
.slice(selectedColumns)
.select { (MangaTable.inLibrary eq true) and (MangaTable.defaultCategory eq true) }
.map(transform)
}
}
return transaction { return transaction {
CategoryMangaTable.innerJoin(MangaTable) // Fetch data from the MangaTable and join with the CategoryMangaTable, if a category is specified
.slice(selectedColumns) val query = if (categoryId == DEFAULT_CATEGORY_ID) {
.select { (MangaTable.inLibrary eq true) and (CategoryMangaTable.category eq categoryId) } MangaTable
.map(transform) .leftJoin(ChapterTable, { MangaTable.id }, { ChapterTable.manga })
.slice(columns = selectedColumns)
.select { (MangaTable.inLibrary eq true) and (MangaTable.defaultCategory eq true) }
} else {
MangaTable
.innerJoin(CategoryMangaTable)
.leftJoin(ChapterTable, { MangaTable.id }, { ChapterTable.manga })
.slice(columns = selectedColumns)
.select { (MangaTable.inLibrary eq true) and (CategoryMangaTable.category eq categoryId) }
}
// Join with the ChapterTable to fetch the last read chapter for each manga
query.groupBy(*MangaTable.columns.toTypedArray()).map(transform)
} }
} }

View File

@@ -45,6 +45,7 @@ data class MangaDataClass(
var unreadCount: Long? = null, var unreadCount: Long? = null,
var downloadCount: Long? = null, var downloadCount: Long? = null,
var chapterCount: Long? = null, var chapterCount: Long? = null,
var lastReadAt: Long? = null,
var lastChapterRead: ChapterDataClass? = null, var lastChapterRead: ChapterDataClass? = null,
val age: Long? = if (lastFetchedAt == null) 0 else Instant.now().epochSecond.minus(lastFetchedAt), val age: Long? = if (lastFetchedAt == null) 0 else Instant.now().epochSecond.minus(lastFetchedAt),