summaryrefslogtreecommitdiff
path: root/Services/SearchService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Services/SearchService.cs')
-rw-r--r--Services/SearchService.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/Services/SearchService.cs b/Services/SearchService.cs
new file mode 100644
index 0000000..5ca12e1
--- /dev/null
+++ b/Services/SearchService.cs
@@ -0,0 +1,117 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace HyperBooru.Services;
+
+public interface ISearchService {
+ public Media[] Search(string query);
+}
+
+public class SearchService : ISearchService {
+ private ITagService tagService;
+
+ private IDbContextFactory<HBContext> dbFactory;
+
+ public SearchService(
+ IDbContextFactory<HBContext> dbFactory,
+ ITagService tagService) {
+
+ this.tagService = tagService;
+ this.dbFactory = dbFactory;
+ }
+
+ public Media[] Search(string query) {
+ var db = dbFactory.CreateDbContext();
+
+ query = query.ToLower().Trim();
+
+ int[] descriptionResults = SearchDescription(query);
+ int[] filenameResults = SearchFilenames(query);
+ int[] ocrResults = SearchOcr(query);
+
+ var matchedTag = db.TagDefinitions
+ .FirstOrDefault(td => td.Name.ToLower() == query);
+
+ int[] tags;
+ if(matchedTag is not null) {
+ tags = tagService
+ .TagsThatImply(matchedTag)
+ .Select(td => td.ObjectId)
+ .ToArray();
+ } else {
+ // TODO: Expand scope to all tags that imply
+ tags = db.TagDefinitions
+ .Where(td => td.Name.ToLower().Contains(query))
+ .Select(td => td.ObjectId)
+ .ToArray();
+ }
+
+ int[] tagResults = SearchTags(tags);
+
+ int[] mediaIds = descriptionResults
+ .Union(filenameResults)
+ .Union(ocrResults)
+ .Union(tagResults)
+ .OrderDescending()
+ .ToArray();
+
+ return db.Media
+ .Include(m => m.Tags)
+ .Include(m => m.CurrentUploadedFile)
+ .Where(m => mediaIds.Contains(m.ObjectId))
+ .ToArray();
+ }
+
+ // TODO: Make asynchronous
+ private int[] SearchDescription(string query) {
+ return Task.Run(() => {
+ using var db = dbFactory.CreateDbContext();
+ query = query.ToLower();
+ return db.Media
+ .Where(m =>
+ (m.ShortDescription != null && m.ShortDescription.ToLower().Contains(query)) ||
+ (m.LongDescription != null && m.LongDescription.ToLower().Contains(query)))
+ .Select(m => m.ObjectId)
+ .ToArray();
+ }).GetAwaiter().GetResult();
+ }
+
+ // TODO: Make asynchronous
+ private int[] SearchFilenames(string query) {
+ return Task.Run(() => {
+ using var db = dbFactory.CreateDbContext();
+ query = query.ToLower();
+ return db.UploadedFiles
+ .Include(uf => uf.Media)
+ .Where(uf => uf.Filename != null && uf.Filename.ToLower().Contains(query))
+ .Select(uf => uf.Media.ObjectId)
+ .Distinct()
+ .ToArray();
+ }).GetAwaiter().GetResult();
+ }
+
+ // TODO: Make asynchronous
+ private int[] SearchOcr(string query) {
+ return Task.Run(() => {
+ using var db = dbFactory.CreateDbContext();
+ query = query.ToLower();
+ return db.OcrData
+ .Include(o => o.Media)
+ .Where(o => o.SearchableText.Contains(query))
+ .Select(o => o.Media.ObjectId)
+ .ToArray();
+ }).GetAwaiter().GetResult();
+ }
+
+ // TODO: Make asynchronous
+ private int[] SearchTags(int[] tags) {
+ return Task.Run(() => {
+ using var db = dbFactory.CreateDbContext();
+ return db.Media
+ .Include(m => m.Tags)
+ .AsEnumerable()
+ .Where(m => m.Tags.IntersectBy(tags, t => t.TagDefinitionId).Any())
+ .Select(m => m.ObjectId)
+ .ToArray();
+ }).GetAwaiter().GetResult();
+ }
+}