diff options
author | crupest <crupest@outlook.com> | 2021-01-16 18:38:17 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-01-16 18:38:17 +0800 |
commit | b91b7bf4c0afb960b392b8187bba959503d99cec (patch) | |
tree | f3d6228f80c3074453003eb4ca94256faaf50a11 /BackEnd/Timeline | |
parent | a23b8af0b06be2ab58d1831a0a25a30d934ec1e2 (diff) | |
download | timeline-b91b7bf4c0afb960b392b8187bba959503d99cec.tar.gz timeline-b91b7bf4c0afb960b392b8187bba959503d99cec.tar.bz2 timeline-b91b7bf4c0afb960b392b8187bba959503d99cec.zip |
feat: Add search service.
Diffstat (limited to 'BackEnd/Timeline')
-rw-r--r-- | BackEnd/Timeline/Services/SearchService.cs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/BackEnd/Timeline/Services/SearchService.cs b/BackEnd/Timeline/Services/SearchService.cs new file mode 100644 index 00000000..eac81fd0 --- /dev/null +++ b/BackEnd/Timeline/Services/SearchService.cs @@ -0,0 +1,98 @@ +using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Timeline.Entities;
+
+namespace Timeline.Services
+{
+ public class SearchResultItem<TItem>
+ {
+ public SearchResultItem(TItem item, int score)
+ {
+ Item = item;
+ Score = score;
+ }
+
+ public TItem Item { get; set; } = default!;
+
+ /// <summary>
+ /// Bigger is better.
+ /// </summary>
+ public int Score { get; set; }
+ }
+
+ public class SearchResult<TItem>
+ {
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List<SearchResultItem<TItem>> Items { get; set; } = new();
+#pragma warning restore CA2227 // Collection properties should be read only
+ }
+
+ public interface ISearchService
+ {
+ /// <summary>
+ /// Search timelines whose name or title contains query string.
+ /// </summary>
+ /// <param name="query">String to contain.</param>
+ /// <returns>Search results.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="query"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="query"/> is empty.</exception>
+ Task<SearchResult<TimelineEntity>> SearchTimeline(string query);
+
+ /// <summary>
+ /// Search users whose username or nickname contains query string.
+ /// </summary>
+ /// <param name="query">String to contain.</param>
+ /// <returns>Search results.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="query"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="query"/> is empty.</exception>
+ Task<SearchResult<UserEntity>> SearchUser(string query);
+ }
+
+ public class SearchService : ISearchService
+ {
+ private readonly DatabaseContext _database;
+
+ public SearchService(DatabaseContext database)
+ {
+ _database = database;
+ }
+
+ public async Task<SearchResult<TimelineEntity>> SearchTimeline(string query)
+ {
+ if (query is null)
+ throw new ArgumentNullException(nameof(query));
+ if (query.Length == 0)
+ throw new ArgumentException("Query string can't be empty.", nameof(query));
+
+ var nameLikeTimelines = await _database.Timelines.Include(t => t.Owner).Where(t => t.Name == null ? t.Owner.Username.Contains(query) : t.Name.Contains(query)).ToListAsync();
+ var titleLikeTimelines = await _database.Timelines.Where(t => t.Title != null && t.Title.Contains(query)).ToListAsync();
+
+ var searchResult = new SearchResult<TimelineEntity>();
+ searchResult.Items.AddRange(nameLikeTimelines.Select(t => new SearchResultItem<TimelineEntity>(t, 2)));
+ searchResult.Items.AddRange(titleLikeTimelines.Select(t => new SearchResultItem<TimelineEntity>(t, 1)));
+
+ return searchResult;
+ }
+
+ public async Task<SearchResult<UserEntity>> SearchUser(string query)
+ {
+ if (query is null)
+ throw new ArgumentNullException(nameof(query));
+ if (query.Length == 0)
+ throw new ArgumentException("Query string can't be empty.", nameof(query));
+
+ var usernameLikeUsers = await _database.Users.Where(u => u.Username.Contains(query)).ToListAsync();
+ var nicknameLikeUsers = await _database.Users.Where(u => u.Nickname != null && u.Nickname.Contains(query)).ToListAsync();
+
+ var searchResult = new SearchResult<UserEntity>();
+ searchResult.Items.AddRange(usernameLikeUsers.Select(u => new SearchResultItem<UserEntity>(u, 2)));
+ searchResult.Items.AddRange(nicknameLikeUsers.Select(u => new SearchResultItem<UserEntity>(u, 1)));
+
+ return searchResult;
+
+ }
+ }
+}
|