Files
bibliomane/internal/query/query.go

251 lines
8.4 KiB
Go

package query
import (
"regexp"
"strings"
"git.artlef.fr/bibliomane/internal/dto"
"git.artlef.fr/bibliomane/internal/fileutils"
"git.artlef.fr/bibliomane/internal/model"
"gorm.io/gorm"
)
func FetchBookGet(db *gorm.DB, userId uint, bookId uint64) (dto.FullBookGet, error) {
var book dto.FullBookGet
query := db.Model(&model.Book{})
selectQueryString := "books.title, authors.name as author, authors.id as author_id, books.isbn, books.inventaire_id, books.open_library_id, books.short_description, books.summary, " +
"user_books.review, user_books.rating, user_books.read, user_books.want_read, " +
"DATE(user_books.start_read_date) as start_read_date, " +
"DATE(user_books.end_read_date) AS end_read_date, " +
selectStaticFilesPath()
query = query.Select(selectQueryString)
query = joinAuthors(query)
query = query.Joins("left join user_books on (user_books.book_id = books.id and user_books.user_id = ?)", userId)
query = joinStaticFiles(query)
query = query.Where("books.id = ?", bookId)
res := query.First(&book)
return book, res.Error
}
func FetchReadUserBook(db *gorm.DB, userId uint, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchReadUserBookQuery(db, userId)
query = query.Limit(limit)
query = query.Offset(offset)
res := query.Find(&books)
return books, res.Error
}
func FetchReadUserBookCount(db *gorm.DB, userId uint) (int64, error) {
query := fetchReadUserBookQuery(db, userId)
var count int64
res := query.Count(&count)
return count, res.Error
}
func FetchReadingUserBook(db *gorm.DB, userId uint, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchReadingUserBookQuery(db, userId)
query = query.Limit(limit)
query = query.Offset(offset)
res := query.Find(&books)
return books, res.Error
}
func FetchReadingUserBookCount(db *gorm.DB, userId uint) (int64, error) {
query := fetchReadingUserBookQuery(db, userId)
var count int64
res := query.Count(&count)
return count, res.Error
}
func fetchReadUserBookQuery(db *gorm.DB, userId uint) *gorm.DB {
query := fetchUserBookGet(db, userId)
query = query.Where("user_books.read IS TRUE")
return query
}
func fetchReadingUserBookQuery(db *gorm.DB, userId uint) *gorm.DB {
query := fetchUserBookGet(db, userId)
query = query.Where("user_books.start_read_date IS NOT NULL AND (user_books.read IS NULL OR user_books.read IS FALSE)")
return query
}
func FetchWantReadUserBook(db *gorm.DB, userId uint, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchWantReadUserBookQuery(db, userId)
query = query.Limit(limit)
query = query.Offset(offset)
res := query.Find(&books)
return books, res.Error
}
func FetchWantReadUserBookCount(db *gorm.DB, userId uint) (int64, error) {
query := fetchWantReadUserBookQuery(db, userId)
var count int64
res := query.Count(&count)
return count, res.Error
}
func fetchWantReadUserBookQuery(db *gorm.DB, userId uint) *gorm.DB {
query := fetchUserBookGet(db, userId)
query = query.Where("user_books.want_read IS TRUE")
return query
}
// fetch only books where userbook exists
func fetchUserBookGet(db *gorm.DB, userId uint) *gorm.DB {
query := db.Model(&model.UserBook{})
query = query.Select(selectBookItem())
query = query.Joins("left join books on (books.id = user_books.book_id)")
query = joinAuthors(query)
query = joinStaticFiles(query)
query = query.Where("user_id = ?", userId)
return query
}
func FetchAllBooks(db *gorm.DB, userId uint, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchBookQueryBuilder(db, userId)
query = query.Limit(limit)
query = query.Offset(offset)
query = query.Order("books.id DESC")
res := query.Find(&books)
return books, res.Error
}
func FetchAllBooksCount(db *gorm.DB, userId uint) (int64, error) {
var count int64
query := fetchBookQueryBuilder(db, userId)
res := query.Count(&count)
return count, res.Error
}
func FetchBookSearchByAuthorGet(db *gorm.DB, userId uint, authorId uint64, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchBookSearchByAuthorQuery(db, userId, authorId)
query = query.Limit(limit)
query = query.Offset(offset)
res := query.Find(&books)
return books, res.Error
}
func FetchBookSearchByAuthorGetCount(db *gorm.DB, userId uint, authorId uint64) (int64, error) {
var count int64
query := fetchBookSearchByAuthorQuery(db, userId, authorId)
res := query.Count(&count)
return count, res.Error
}
func fetchBookSearchByAuthorQuery(db *gorm.DB, userId uint, authorId uint64) *gorm.DB {
query := fetchBookQueryBuilder(db, userId)
return query.Where("authors.id = ?", authorId)
}
func FetchBookSearchGet(db *gorm.DB, userId uint, searchterm string, limit int, offset int) ([]dto.BookItemGet, error) {
var books []dto.BookItemGet
query := fetchBookSearchQuery(db, userId, searchterm)
query = query.Limit(limit)
query = query.Offset(offset)
res := query.Find(&books)
return books, res.Error
}
func FetchBookSearchGetCount(db *gorm.DB, userId uint, searchterm string) (int64, error) {
query := fetchBookSearchQuery(db, userId, searchterm)
var count int64
res := query.Count(&count)
return count, res.Error
}
func fetchBookSearchQuery(db *gorm.DB, userId uint, searchterm string) *gorm.DB {
query := fetchBookQueryBuilder(db, userId)
isIsbn, _ := regexp.Match(`\d{10,13}`, []byte(searchterm))
if isIsbn {
query = query.Where("books.isbn = ?", searchterm)
} else {
query = query.Where("LOWER(books.title) LIKE ?", "%"+strings.ToLower(searchterm)+"%")
}
return query
}
// fetch all books even whithout user books
func fetchBookQueryBuilder(db *gorm.DB, userId uint) *gorm.DB {
query := db.Model(&model.Book{})
query = query.Select(selectBookItem())
query = joinAuthors(query)
query = query.Joins("left join user_books on (user_books.book_id = books.id and user_books.user_id = ?)", userId)
query = joinStaticFiles(query)
return query
}
func selectBookItem() string {
return "books.id, books.title, authors.name as author, books.short_description as description, books.inventaire_id, user_books.rating, user_books.read, DATE(user_books.start_read_date) as start_read_date, user_books.want_read, " + selectStaticFilesPath()
}
type CollectionsQueryResult struct {
ID uint
Name string
BookId uint
BookTitle string
CoverPath string
}
type collectionId struct {
ID uint
}
func FetchAllCollections(db *gorm.DB, userId uint, limit int, offset int) ([]CollectionsQueryResult, error) {
var collections []CollectionsQueryResult
var collectionIds []collectionId
res := fetchCollections(db, userId).Limit(limit).Offset(offset).Order("collections.id DESC").Find(&collectionIds)
if res.Error != nil {
return collections, res.Error
}
for _, collectionId := range collectionIds {
queryResults, err := queryBooksForCollection(db, collectionId.ID)
if err != nil {
return collections, res.Error
}
collections = append(collections, queryResults...)
}
return collections, res.Error
}
func queryBooksForCollection(db *gorm.DB, collectionId uint) ([]CollectionsQueryResult, error) {
var collections []CollectionsQueryResult
query := db.Model(&model.Collection{})
query = query.Select("collections.id, collections.name, books.id as book_id, books.title as book_title, " + selectStaticFilesPath())
query = query.Joins("left join collection_books on (collection_books.collection_id = collections.id)")
query = query.Joins("left join books on (books.id = collection_books.book_id)")
query = joinStaticFiles(query)
query = query.Where("collections.id = ?", collectionId)
//only takes first 5 books
query = query.Limit(5)
res := query.Find(&collections)
return collections, res.Error
}
func FetchAllCollectionsCount(db *gorm.DB, userId uint) (int64, error) {
var count int64
res := fetchCollections(db, userId).Count(&count)
return count, res.Error
}
func fetchCollections(db *gorm.DB, userId uint) *gorm.DB {
return db.Model(&model.Collection{}).Where("collections.user_id = ?", userId)
}
func selectStaticFilesPath() string {
return "(CASE COALESCE(static_files.path, '') WHEN '' THEN '' ELSE concat('" + fileutils.GetWsLinkPrefix() + "', static_files.path) END) as CoverPath"
}
func joinAuthors(query *gorm.DB) *gorm.DB {
return query.Joins("left join authors on (authors.id = books.author_id)")
}
func joinStaticFiles(query *gorm.DB) *gorm.DB {
return query.Joins("left join static_files on (static_files.id = books.cover_id)")
}