Search should include title texts wherever title carries important context

#506
This commit is contained in:
Hamid Reza Mohammadi 2026-09-04 15:55:07 +03:30
parent ef5b61bf03
commit 32041f4e65
6 changed files with 40 additions and 8 deletions

View File

@ -24346,7 +24346,7 @@
</member> </member>
<member name="T:RMuseum.Utils.PublicDataImport.HttpPublicDataSource"> <member name="T:RMuseum.Utils.PublicDataImport.HttpPublicDataSource">
<summary> <summary>
Fetches over HTTP — point <paramref name="baseUrl"/> at either the jsDelivr CDN URL Fetches over HTTP — point <c>baseUrl</c> at either the jsDelivr CDN URL
(https://cdn.jsdelivr.net/gh/ORG/REPO@main/) or raw.githubusercontent.com. A missing file (https://cdn.jsdelivr.net/gh/ORG/REPO@main/) or raw.githubusercontent.com. A missing file
(404) is treated the same as "doesn't exist", not an error. (404) is treated the same as "doesn't exist", not an error.
</summary> </summary>

View File

@ -188,14 +188,46 @@ namespace RMuseum.Services.Implementation
} }
private static readonly Regex _titleNumberRegex = new Regex(@"[۰-۹٠-٩0-9]+", RegexOptions.Compiled);
private static readonly char[] _titleTrimChars = new[] { ' ', '\t', '\r', '\n', '\u200c', '\u200f', '\u200e', '-', '–', '—', ':', '،', ',', '.', '(', ')', '[', ']', '"', '\'', '«', '»' };
/// <summary>
/// extracts the searchable part of a poem title, discarding pure boilerplate like
/// "غزل شمارهٔ ۱" or "بخش ۴۷" which carries no information beyond the ordinal number,
/// while keeping either the whole title (if it has no number at all, e.g. "طهمورث")
/// or just the descriptive part after the number (e.g. "بخش ۴۷ - تشبیه کردن قرآن..."
/// keeps "تشبیه کردن قرآن...") - returns "" when there is nothing worth indexing
/// </summary>
/// <param name="title"></param>
/// <returns></returns>
private static string ExtractSearchableTitlePart(string title)
{
if (string.IsNullOrWhiteSpace(title))
return "";
Match m = _titleNumberRegex.Match(title);
if (!m.Success)
return title.Trim(_titleTrimChars);
return title.Substring(m.Index + m.Length).Trim(_titleTrimChars);
}
/// <summary> /// <summary>
/// make plain text /// make plain text
/// </summary> /// </summary>
/// <param name="verses"></param> /// <param name="verses"></param>
/// <param name="title">poem/section title - its searchable part (if any) is included so
/// titles like "بخش ۴۷ - تشبیه کردن ..." are findable through search, while pure
/// boilerplate like "غزل شمارهٔ ۱" is silently skipped</param>
/// <returns></returns> /// <returns></returns>
private static string PreparePlainText(List<GanjoorVerse> verses) private static string PreparePlainText(List<GanjoorVerse> verses, string title = null)
{ {
string plainText = ""; string plainText = "";
string searchableTitle = ExtractSearchableTitlePart(title);
if (!string.IsNullOrEmpty(searchableTitle))
{
plainText += $"{LanguageUtils.MakeTextSearchable(searchableTitle)}{Environment.NewLine}";
}
foreach (GanjoorVerse verse in verses) foreach (GanjoorVerse verse in verses)
{ {
plainText += $"{LanguageUtils.MakeTextSearchable(verse.Text)}{Environment.NewLine}";//replace zwnj with space plainText += $"{LanguageUtils.MakeTextSearchable(verse.Text)}{Environment.NewLine}";//replace zwnj with space
@ -238,7 +270,7 @@ namespace RMuseum.Services.Implementation
var verses = await context.GanjoorVerses.AsNoTracking().Where(v => v.PoemId == poem.Id).OrderBy(v => v.VOrder).ToListAsync(); var verses = await context.GanjoorVerses.AsNoTracking().Where(v => v.PoemId == poem.Id).OrderBy(v => v.VOrder).ToListAsync();
poem.PlainText = PreparePlainText(verses); poem.PlainText = PreparePlainText(verses, poem.Title);
poem.HtmlText = PrepareHtmlText(verses); poem.HtmlText = PrepareHtmlText(verses);
} }

View File

@ -185,7 +185,7 @@ namespace RMuseum.Services.Implementation
{ {
_context.UpdateRange(modifiedVerses); _context.UpdateRange(modifiedVerses);
dbPoem.HtmlText = PrepareHtmlText(poemVerses); dbPoem.HtmlText = PrepareHtmlText(poemVerses);
dbPoem.PlainText = PreparePlainText(poemVerses); dbPoem.PlainText = PreparePlainText(poemVerses, dbPoem.Title);
dbPage.HtmlText = dbPoem.HtmlText; dbPage.HtmlText = dbPoem.HtmlText;
updatePoem = true; updatePoem = true;
} }
@ -313,7 +313,7 @@ namespace RMuseum.Services.Implementation
} }
_context.UpdateRange(undeletedPoemVerss); _context.UpdateRange(undeletedPoemVerss);
dbPoem.HtmlText = PrepareHtmlText(undeletedPoemVerss); dbPoem.HtmlText = PrepareHtmlText(undeletedPoemVerss);
dbPoem.PlainText = PreparePlainText(undeletedPoemVerss); dbPoem.PlainText = PreparePlainText(undeletedPoemVerss, dbPoem.Title);
dbPage.HtmlText = dbPoem.HtmlText; dbPage.HtmlText = dbPoem.HtmlText;
updatePoem = true; updatePoem = true;
poemVerses = undeletedPoemVerss; poemVerses = undeletedPoemVerss;

View File

@ -944,7 +944,7 @@ namespace RMuseum.Services.Implementation
var dbPoem = await _context.GanjoorPoems.Include(p => p.GanjoorMetre).Where(p => p.Id == poemId).SingleAsync(); var dbPoem = await _context.GanjoorPoems.Include(p => p.GanjoorMetre).Where(p => p.Id == poemId).SingleAsync();
var dbPage = await _context.GanjoorPages.Where(p => p.Id == poemId).SingleAsync(); var dbPage = await _context.GanjoorPages.Where(p => p.Id == poemId).SingleAsync();
dbPoem.HtmlText = PrepareHtmlText(poemVerses); dbPoem.HtmlText = PrepareHtmlText(poemVerses);
dbPoem.PlainText = PreparePlainText(poemVerses); dbPoem.PlainText = PreparePlainText(poemVerses, dbPoem.Title);
dbPage.HtmlText = dbPoem.HtmlText; dbPage.HtmlText = dbPoem.HtmlText;
_context.Update(dbPoem); _context.Update(dbPoem);
_context.Update(dbPage); _context.Update(dbPage);

View File

@ -527,7 +527,7 @@ namespace RMuseum.Services.Implementation
context.GanjoorVerses.UpdateRange(poemVerses); context.GanjoorVerses.UpdateRange(poemVerses);
} }
dbPoem.PlainText = PreparePlainText(poemVerses); dbPoem.PlainText = PreparePlainText(poemVerses, dbPoem.Title);
dbPoem.HtmlText = PrepareHtmlText(poemVerses); dbPoem.HtmlText = PrepareHtmlText(poemVerses);
dbPage.HtmlText = dbPoem.HtmlText; dbPage.HtmlText = dbPoem.HtmlText;
dbPage.Title = dbPoem.Title; dbPage.Title = dbPoem.Title;

View File

@ -437,7 +437,7 @@ namespace RMuseum.Services.Implementation
continue; continue;
} }
dbPoem.PlainText = PreparePlainText(poemVerses); dbPoem.PlainText = PreparePlainText(poemVerses, dbPoem.Title);
dbPoem.HtmlText = PrepareHtmlText(poemVerses); dbPoem.HtmlText = PrepareHtmlText(poemVerses);
context.GanjoorPoems.Add(dbPoem); context.GanjoorPoems.Add(dbPoem);