예제 #1
0
    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);
        }