private async Task <IEnumerable <SearchResultItem> > SearchCore(string searchText) { var source = await _bkRepo.GetAllAsync(); var tags = await _tagRepo.GetAllAsync(); if (string.IsNullOrWhiteSpace(searchText)) { var latest = source .Where(x => x.LastClickTime > 0 && x.ClickedCount > 0) .OrderByDescending(x => x.LastClickTime) .ThenByDescending(x => x.ClickedCount) .Select(x => x.Id) .Take(LatestCount) .ToList(); return(source .Select(x => { var r = new SearchResultItem(x) { LastClickTime = x.LastClickTime }; r.AddScore(ScoreReason.Const, 10); if (latest.FirstOrDefault(a => a == r.Bk.Id) != null) { r.AddScore(ScoreReason.Latest, 10 - latest.FindIndex(a => a == r.Bk.Id)); } return r; })); } var input = SearchInput.Parse(searchText); _logger.LogInformation( "Search text parse result, SourceText: {SearchInput} Keywords: {Keywords}, Tags: {Tags}", input.SourceText, input.Keywords, input.Tags); var tagDict = tags.ToDictionary(x => x.Tag); var matchTags = tagDict .Where(tag => input.Tags.Contains(tag.Key) || input.Keywords.Any(keyword => StringContains(tag.Key, keyword))) .Select(x => x.Key) .ToHashSet(); var matchTagAlias = tagDict .Where(tag => input.Keywords.Any(keyword => tag.Value.TagAlias.Values.Any(tagAlias => StringContains(tagAlias.Alias, keyword)))) .Select(x => x.Key) .ToHashSet(); var re = source .Select(MatchBk) .Where(x => x.Matched); return(re); SearchResultItem MatchBk(Bk item) { var result = new SearchResultItem(item) { ClickCount = item.ClickedCount, LastClickTime = item.LastClickTime }; result.AddScore(ScoreReason.Title, input.Keywords.Any(x => StringContains(item.Title, x))); result.AddScore(ScoreReason.TitleAlias, item.TitleAlias?.Values != null && item.TitleAlias.Values.Any(al => input.Keywords.Any(x => StringContains(al.Alias, x)))); result.AddScore(ScoreReason.Url, input.Keywords.Any(x => StringContains(item.Url, x))); if (item.Tags?.Any() == true) { result.AddScore(ScoreReason.Tags, item.Tags.Any(matchTags.Contains)); result.AddScore(ScoreReason.TagAlias, item.Tags.Any(matchTagAlias.Contains)); } if (result.Score > 0) { result.AddScore(ScoreReason.ClickCount, item.ClickedCount); } return(result); }