Added generic collections of objects

This commit is contained in:
schnulller
2022-06-22 14:57:09 +02:00
parent ba3d63ffba
commit 83b4e5327a
3 changed files with 31 additions and 12 deletions

View File

@@ -69,19 +69,22 @@ public class SucheController : Controller {
var lib = _lib.GetLibrary(); var lib = _lib.GetLibrary();
List<IGrouping<int, Meta>>? metasbyyear = null; List<IGrouping<int, Meta>>? metasbyyear = null;
if (search != null) { if (search != null) {
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
search = search.Trim(); search = search.Trim();
var res = _xmlService.SearchCollection("letters", search, _readerService); var res = _xmlService.SearchCollection("letters", search, _readerService);
if (res == null || !res.Any()) return _error404(); if (res == null || !res.Any()) return _error404();
var ret = res.ToDictionary( var ret = res.ToDictionary(
x => x.Index, x => x.Index,
x => x.Results x => x.Results
.Select(y => new SearchResult(search, x.Index) { Page = y.Page, Line = y.Line, Preview = y.Preview}) .Select(y => new SearchResult(search, x.Index) { Page = y.Page, Line = y.Line, Preview = y.Preview })
.ToList() .ToList()
); );
var keys = res.Select(x => x.Index).Where(x => lib.Metas.ContainsKey(x)).Select(x => lib.Metas[x]); var keys = res.Select(x => x.Index).Where(x => lib.Metas.ContainsKey(x)).Select(x => lib.Metas[x]);
var letters = keys.ToLookup(x => x.Sort.Year).OrderBy(x => x.Key).ToList(); var letters = keys.ToLookup(x => x.Sort.Year).OrderBy(x => x.Key).ToList();
stopwatch.Stop();
Console.WriteLine("SEARCH: " + stopwatch.ElapsedMilliseconds);
return _paginateSend(lib, page, letters, null, null, null, search, ret); return _paginateSend(lib, page, letters, null, null, null, search, ret);
} }
metasbyyear = lib.MetasByYear.OrderBy(x => x.Key).ToList(); metasbyyear = lib.MetasByYear.OrderBy(x => x.Key).ToList();
return _paginateSend(lib, page, metasbyyear); return _paginateSend(lib, page, metasbyyear);
@@ -105,7 +108,7 @@ public class SucheController : Controller {
private List<(string Key, string Person)> _getAvailablePersons(ILibrary lib) { private List<(string Key, string Person)> _getAvailablePersons(ILibrary lib) {
return lib.Persons return lib.Persons
.OrderBy(x => x.Value.Surname) .OrderBy(x => x.Value.Surname)
.ThenBy(x => x.Value.Prename) .ThenBy(x => x.Value.Prename)
.Select(x => (x.Key, x.Value.Name)) .Select(x => (x.Key, x.Value.Name))
.ToList(); .ToList();
} }
@@ -121,7 +124,7 @@ public class SucheController : Controller {
ParsedReceivers = HTMLHelpers.StringHelpers.GetEnumerationString(recivers) ParsedReceivers = HTMLHelpers.StringHelpers.GetEnumerationString(recivers)
}; };
} }
private List<(int StartYear, int EndYear)>? _paginate(List<IGrouping<int, Meta>>? letters) { private List<(int StartYear, int EndYear)>? _paginate(List<IGrouping<int, Meta>>? letters) {
if (letters == null || !letters.Any()) return null; if (letters == null || !letters.Any()) return null;
List<(int StartYear, int EndYear)>? res = null; List<(int StartYear, int EndYear)>? res = null;

View File

@@ -17,8 +17,15 @@ public interface IXMLRoot {
// Key: the key under which the element(s) will be files // Key: the key under which the element(s) will be files
// xPath: the (absolute) XPath to the element(s) // xPath: the (absolute) XPath to the element(s)
// KeyFunc: How to extrect an identifier for the single element in the collection // KeyFunc: How to extrect an identifier for the single element in the collection
// LookupsFunc: Function to generate metadata fields for the object, which will then in turn be a possibility to seach and filter without parsing
// Searchable: Will the element be indexed for full-text-search? // Searchable: Will the element be indexed for full-text-search?
public abstract (string Key, string xPath, Func<XElement, string?> KeyFunc, bool Searchable)[]? XPathCollection { get; } public abstract (
string Key,
string xPath,
Func<XElement, string?> KeyFunc,
// Func<XElement, Dictionary<string, string[]>> LookupsFunc,
bool Searchable
)[]? XPathCollection { get; }
// Determines child objects to be collected // Determines child objects to be collected
// (deprecated see collections above; only used internally) // (deprecated see collections above; only used internally)

View File

@@ -61,15 +61,22 @@ public class XMLService : IXMLService {
public void SetInProduction(XDocument document) { public void SetInProduction(XDocument document) {
if (document == null || _Roots == null) return; if (document == null || _Roots == null) return;
var ret = new ConcurrentDictionary<string, ConcurrentDictionary<string, CollectedItem>>(); int numProcs = Environment.ProcessorCount;
Parallel.ForEach(_Roots, (root) => { int concurrencyLevel = numProcs * 2;
int startingSize = 2909;
int startingSizeAllCollections = 23;
var ret = new ConcurrentDictionary<string, ConcurrentDictionary<string, CollectedItem>>(concurrencyLevel, startingSizeAllCollections);
// Note Parallelization brings almost nothing to the table (on a laptop) here and below.
// Parallel.ForEach(_Roots, (root) => {
foreach (var root in _Roots) {
if (root.Value.XPathCollection != null) if (root.Value.XPathCollection != null)
foreach (var coll in root.Value.XPathCollection) { foreach (var coll in root.Value.XPathCollection) {
var elem = document.XPathSelectElements(coll.xPath); var elem = document.XPathSelectElements(coll.xPath);
if (elem != null && elem.Any()) { if (elem != null && elem.Any()) {
if (!ret.ContainsKey(coll.Key)) if (!ret.ContainsKey(coll.Key))
ret[coll.Key] = new ConcurrentDictionary<string, CollectedItem>(); ret[coll.Key] = new ConcurrentDictionary<string, CollectedItem>(concurrencyLevel, startingSize);
foreach(var e in elem) { Parallel.ForEach(elem, (e) => {
// foreach(var e in elem) {
var k = coll.KeyFunc(e); var k = coll.KeyFunc(e);
if (k != null) { if (k != null) {
var searchtext = coll.Searchable ? var searchtext = coll.Searchable ?
@@ -77,10 +84,12 @@ public class XMLService : IXMLService {
null; null;
ret[coll.Key][k] = new CollectedItem(k, e, root.Value, coll.Key, searchtext); ret[coll.Key][k] = new CollectedItem(k, e, root.Value, coll.Key, searchtext);
} }
} // }
});
} }
} }
}); }
// });
_collectedProduction = ret.ToDictionary(x => x.Key, y => y.Value.ToDictionary(z => z.Key, f => f.Value, null), null); _collectedProduction = ret.ToDictionary(x => x.Key, y => y.Value.ToDictionary(z => z.Key, f => f.Value, null), null);
} }