using Bibblan.Models; using Bibblan.ViewModels; using Dapper; using Microsoft.Extensions.Options; using Npgsql; namespace Bibblan.Business.Services { public class BookFilter { public int? Author; public string? Query; } public class DatabaseService { BibblanOptions settings; public DatabaseService(IOptions options) { settings = options.Value; } public IEnumerable GetBooks(int count, BookFilter filter = null) { var conn = new NpgsqlConnection(settings.BibblanConnection); var query = "select * from books"; if(filter != null) { query += " where "; if(filter.Author != null) { query += $"id in (select book from books_authors_link where author = {filter.Author})"; } else if(!String.IsNullOrWhiteSpace(query)) { filter.Query = filter.Query.ToLowerInvariant(); query += $"lower(title) like '%{filter.Query}%' or lower(author_sort) like '%{filter.Query}%'"; } } return conn.Query(query).Take(count).ToList(); } public IEnumerable GetAuthors(int count, BookFilter filter = null) { var query = "select a.id, a.name, count(bal.*) as bookcount\r\nfrom authors a\r\nleft join books_authors_link bal on a.id = bal.author\r\ngroup by a.id , a.name "; if(!String.IsNullOrWhiteSpace(filter?.Query)) { filter.Query = filter.Query.ToLowerInvariant(); query += $" having lower(a.name) like '%{filter.Query}%'"; } var conn = new NpgsqlConnection(settings.BibblanConnection); return conn.Query(query).Take(count).ToList(); } internal List GetSeries(int count, BookFilter? filter) { var query = @"select s.id as seriesid, s.name as seriesname, b.*, a.* --b.id as bookid, b.title, b.pubdate, b.series_index, --a.id as authorid, a.name as authorname from series s inner join books_series_link bsl on s.id = bsl.series inner join books b on bsl.book = b.id inner join books_authors_link bal on b.id = bal.book inner join authors a on bal.author = a.id"; if (!String.IsNullOrWhiteSpace(filter?.Query)) { filter.Query = filter.Query?.ToLowerInvariant().Trim() ?? ""; query += $" where lower(s.name) like '%{filter.Query}%'"; } var conn = new NpgsqlConnection(settings.BibblanConnection); var lookup = new Dictionary(); conn.Query(query, (s,b,a) => { SeriesVm svm; if (!lookup.TryGetValue(s.Id, out svm)) { lookup.Add(s.Id, svm = s); } svm.Books.Add(new ListBook { AuthorId = a.Id, AuthorName = a.Name, Id = b.Id, PubDate = b.Pubdate, SeriesIndex = b.SeriesIndex, Title = b.Title }); return svm; }, splitOn: "id").Take(count).ToList(); return lookup.Values.AsList(); } internal List GetTags(BookFilter? filter) { var query = @"select t.id, t.name, count(btl.*) as bookcount from tags t inner join books_tags_link btl on t.id = btl.tag group by t.id, t.name order by bookcount desc"; if (!String.IsNullOrWhiteSpace(filter?.Query)) { filter.Query = filter.Query.ToLowerInvariant(); query += $" having lower(name) like '%{filter.Query}%'"; } var conn = new NpgsqlConnection(settings.BibblanConnection); return conn.Query(query).ToList(); } } }