139 lines
4.9 KiB
C#
139 lines
4.9 KiB
C#
using DuoVia.FuzzyStrings;
|
|
using NTDLS.Helpers;
|
|
using ZelWiki.Caching;
|
|
using ZelWiki.Engine.Library;
|
|
using ZelWiki.Engine.Library.Interfaces;
|
|
using ZelWiki.Library.Interfaces;
|
|
using ZelWiki.Models.DataModels;
|
|
using ZelWiki.Repository;
|
|
|
|
namespace ZelWiki.Engine.Implementation
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class Helpers
|
|
{
|
|
/// <summary>
|
|
/// 更新页面 如果Id为0则新增页面
|
|
/// </summary>
|
|
/// <param name="wikifier"></param>
|
|
/// <param name="page"></param>
|
|
/// <param name="sessionState"></param>
|
|
/// <returns></returns>
|
|
public static int UpsertPage(IZelEngine wikifier, Page page, ISessionState? sessionState = null)
|
|
{
|
|
var isNewlyCreated = page.Id == 0;
|
|
|
|
page.Id = PageRepository.SavePage(page);
|
|
|
|
RefreshPageMetadata(wikifier, page, sessionState);
|
|
|
|
if (isNewlyCreated)
|
|
PageRepository.UpdateSinglePageReference(page.Navigation, page.Id);
|
|
|
|
|
|
return page.Id;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 重建页面并将所有方面写入数据库
|
|
/// </summary>
|
|
/// <param name="wikifier"></param>
|
|
/// <param name="page"></param>
|
|
/// <param name="sessionState"></param>
|
|
public static void RefreshPageMetadata(IZelEngine wikifier, Page page, ISessionState? sessionState = null)
|
|
{
|
|
var state = wikifier.Transform(sessionState, page, null,
|
|
[Constants.WikiMatchType.StandardFunction]);
|
|
|
|
PageRepository.UpdatePageTags(page.Id, state.Tags);
|
|
PageRepository.UpdatePageProcessingInstructions(page.Id, state.ProcessingInstructions);
|
|
|
|
var pageTokens = ParsePageTokens(state).Select(o =>
|
|
new PageToken
|
|
{
|
|
PageId = page.Id,
|
|
Token = o.Token,
|
|
DoubleMetaphone = o.DoubleMetaphone,
|
|
Weight = o.Weight
|
|
}).ToList();
|
|
|
|
PageRepository.SavePageSearchTokens(pageTokens);
|
|
|
|
PageRepository.UpdatePageReferences(page.Id, state.OutgoingLinks);
|
|
|
|
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.Page, [page.Id]));
|
|
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.Page, [page.Navigation]));
|
|
}
|
|
|
|
#region Private
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="state"></param>
|
|
/// <returns></returns>
|
|
private static List<AggregatedSearchToken> ParsePageTokens(IZelEngineState state)
|
|
{
|
|
var parsedTokens = new List<WeightedSearchToken>();
|
|
|
|
parsedTokens.AddRange(ComputeParsedPageTokens(state.HtmlResult, 1));
|
|
parsedTokens.AddRange(ComputeParsedPageTokens(state.Page.Description, 1.2));
|
|
parsedTokens.AddRange(ComputeParsedPageTokens(string.Join(" ", state.Tags), 1.4));
|
|
parsedTokens.AddRange(ComputeParsedPageTokens(state.Page.Name, 1.6));
|
|
|
|
var aggregatedTokens = parsedTokens.GroupBy(o => o.Token).Select(o => new AggregatedSearchToken
|
|
{
|
|
Token = o.Key,
|
|
DoubleMetaphone = o.Key.ToDoubleMetaphone(),
|
|
Weight = o.Sum(g => g.Weight)
|
|
}).ToList();
|
|
|
|
return aggregatedTokens;
|
|
}
|
|
|
|
private static List<WeightedSearchToken> ComputeParsedPageTokens(string content, double weightMultiplier)
|
|
{
|
|
var searchConfig = ConfigurationRepository.GetConfigurationEntryValuesByGroupName("Search");
|
|
|
|
var exclusionWords = searchConfig?.Value<string>("Word Exclusions")?
|
|
.Split([',', ';'], StringSplitOptions.RemoveEmptyEntries).Distinct() ?? new List<string>();
|
|
var strippedContent = Html.StripHtml(content);
|
|
|
|
var tokens = strippedContent.Split([' ', '\n', '\t', '-', '_']).ToList();
|
|
|
|
if (searchConfig?.Value<bool>("Split Camel Case") == true)
|
|
{
|
|
var allSplitTokens = new List<string>();
|
|
|
|
foreach (var token in tokens)
|
|
{
|
|
var splitTokens = Text.SplitCamelCase(token);
|
|
if (splitTokens.Count > 1)
|
|
{
|
|
splitTokens.ForEach(t => allSplitTokens.Add(t));
|
|
}
|
|
}
|
|
|
|
tokens.AddRange(allSplitTokens);
|
|
}
|
|
|
|
tokens = tokens.ConvertAll(d => d.ToLowerInvariant());
|
|
|
|
tokens.RemoveAll(o => exclusionWords.Contains(o));
|
|
|
|
var searchTokens = (from w in tokens
|
|
group w by w
|
|
into g
|
|
select new WeightedSearchToken
|
|
{
|
|
Token = g.Key,
|
|
Weight = g.Count() * weightMultiplier
|
|
}).ToList();
|
|
|
|
return searchTokens.Where(o => string.IsNullOrWhiteSpace(o.Token) == false).ToList();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |