2using System.Collections.Generic;
3using System.Globalization;
5using System.Reflection;
7using System.Threading.Tasks;
32 private static Dictionary<string, bool> stopWords =
new Dictionary<string, bool>();
34 private static Dictionary<string, CollectionInformation> collections;
35 private static Dictionary<string, IPersistentDictionary> indices;
36 private static Dictionary<Type, TypeInformation> types;
52 collections =
new Dictionary<string, CollectionInformation>();
53 indices =
new Dictionary<string, IPersistentDictionary>();
54 types =
new Dictionary<Type, TypeInformation>();
59 Database.ObjectInserted += this.Database_ObjectInserted;
60 Database.ObjectUpdated += this.Database_ObjectUpdated;
61 Database.ObjectDeleted += this.Database_ObjectDeleted;
62 Database.CollectionCleared += this.Database_CollectionCleared;
64 Types.OnInvalidated += this.Types_OnInvalidated;
72 Database.ObjectInserted -= this.Database_ObjectInserted;
73 Database.ObjectUpdated -= this.Database_ObjectUpdated;
74 Database.ObjectDeleted -= this.Database_ObjectDeleted;
75 Database.CollectionCleared -= this.Database_CollectionCleared;
77 Types.OnInvalidated -= this.Types_OnInvalidated;
81 await synchObj.BeginWrite();
87 if (!(indices is
null))
96 collectionInformation?.Dispose();
97 collectionInformation =
null;
108 await synchObj.EndWrite();
115 Task.Run(() => this.ObjectInserted(e));
122 Tuple<CollectionInformation, TypeInformation, GenericObject> P = await Prepare(e.
Object);
127 if (ObjectId is
null)
131 TypeInformation TypeInfo = P.Item2;
138 IndexName = TypeInfo.GetIndexCollection(e.
Object);
147 if (Tokens.Length == 0)
152 await synchObj.BeginWrite();
155 ulong Index = await GetNextIndexNrLocked(IndexName);
159 IndexCollection = IndexName,
161 ObjectInstanceId = ObjectId,
164 Indexed = DateTime.UtcNow
167 await AddTokensToIndexLocked(Ref);
172 await synchObj.EndWrite();
185 private static async Task<IPersistentDictionary> GetIndexLocked(
string IndexCollection,
bool CreateIfNotFound)
190 if (CreateIfNotFound)
193 indices[IndexCollection] = Result;
201 DateTime TP = DateTime.UtcNow;
214 ObjectReferences =
new ulong[] { Ref.Index },
215 Counts =
new uint[] { (uint)Token.
DocIndex.Length },
216 Timestamps =
new DateTime[] { TP }
223 ulong[] NewReferences =
new ulong[c + 1];
224 uint[] NewCounts =
new uint[c + 1];
225 DateTime[] NewTimestamps =
new DateTime[c + 1];
227 Array.Copy(References.ObjectReferences, 0, NewReferences, 0, c);
228 Array.Copy(References.Counts, 0, NewCounts, 0, c);
229 Array.Copy(References.Timestamps, 0, NewTimestamps, 0, c);
231 NewReferences[c] = Ref.
Index;
232 NewCounts[c] = (uint)Token.
DocIndex.Length;
233 NewTimestamps[c] = TP;
235 References.ObjectReferences = NewReferences;
236 References.Counts = NewCounts;
237 References.Timestamps = NewTimestamps;
243 References.LastBlock++;
248 Counts = References.
Counts,
249 ObjectReferences = References.ObjectReferences,
250 Timestamps = References.Timestamps
253 await Index.
AddAsync(Token.
Token +
" " + References.LastBlock.ToString(), NewBlock,
true);
255 References.ObjectReferences =
new ulong[] { Ref.Index };
256 References.Counts =
new uint[] { (uint)Token.
DocIndex.Length };
257 References.Timestamps =
new DateTime[] { TP };
262 Token.Block = References.LastBlock + 1;
266 private static async Task<ulong> GetNextIndexNrLocked(
string IndexedCollection)
268 string Key =
" C(" + IndexedCollection +
")";
269 KeyValuePair<bool, object> P = await collectionInformation.
TryGetValueAsync(Key);
271 if (!P.Key || !(P.Value is ulong Nr))
276 await collectionInformation.
AddAsync(Key, Nr,
true);
281 private static Task<CollectionInformation> GetCollectionInfoLocked(
string CollectionName,
bool CreateIfNotExists)
283 return GetCollectionInfoLocked(CollectionName, CollectionName, CreateIfNotExists);
286 private static async Task<CollectionInformation> GetCollectionInfoLocked(
287 string IndexCollectionName,
string CollectionName,
bool CreateIfNotExists)
292 KeyValuePair<bool, object> P = await collectionInformation.
TryGetValueAsync(CollectionName);
295 collections[CollectionName] = Result2;
299 if (!CreateIfNotExists)
303 collections[CollectionName] = Result;
304 await collectionInformation.
AddAsync(CollectionName, Result,
true);
315 Dictionary<string, List<string>> ByIndex =
new Dictionary<string, List<string>>();
317 await synchObj.BeginRead();
320 foreach (
object Obj
in await collectionInformation.
GetValuesAsync())
324 if (!ByIndex.TryGetValue(Info.IndexCollectionName, out List<string> Collections))
326 Collections =
new List<string>();
327 ByIndex[Info.IndexCollectionName] = Collections;
330 Collections.Add(Info.CollectionName);
336 await synchObj.EndRead();
339 Dictionary<string, string[]> Result =
new Dictionary<string, string[]>();
341 foreach (KeyValuePair<
string, List<string>> Rec
in ByIndex)
342 Result[Rec.Key] = Rec.Value.ToArray();
355 await synchObj.BeginRead();
358 return await GetCollectionNamesLocked(IndexCollectionName);
362 await synchObj.EndRead();
372 private static async Task<string[]> GetCollectionNamesLocked(
string IndexCollectionName)
374 List<string> Result =
new List<string>();
376 foreach (
object Obj
in await collectionInformation.
GetValuesAsync())
380 if (Info.IndexCollectionName == IndexCollectionName)
381 Result.Add(Info.CollectionName);
385 return Result.ToArray();
394 internal static async Task<bool> SetFullTextSearchIndexCollection(
string IndexCollection,
string CollectionName)
396 await synchObj.BeginWrite();
405 Info = await GetCollectionInfoLocked(IndexCollection, CollectionName,
true);
412 Info.IndexCollectionName = IndexCollection;
422 await synchObj.EndWrite();
432 internal static async Task<bool> AddFullTextSearch(
string CollectionName, params
PropertyDefinition[] Properties)
434 await synchObj.BeginWrite();
449 await synchObj.EndWrite();
459 internal static async Task<bool> RemoveFullTextSearch(
string CollectionName, params
PropertyDefinition[] Properties)
461 await synchObj.BeginWrite();
476 await synchObj.EndWrite();
484 internal static async Task<Dictionary<string, PropertyDefinition[]>> GetFullTextSearchIndexedProperties()
486 Dictionary<string, PropertyDefinition[]> Result =
new Dictionary<string, PropertyDefinition[]>();
488 await synchObj.BeginRead();
491 foreach (
object Obj
in await collectionInformation.
GetValuesAsync())
499 await synchObj.EndRead();
510 internal static async Task<PropertyDefinition[]> GetFullTextSearchIndexedProperties(
string CollectionName)
512 await synchObj.BeginRead();
524 await synchObj.EndRead();
528 private static async Task<Tuple<CollectionInformation, TypeInformation, GenericObject>> Prepare(
object Object)
532 await synchObj.BeginWrite();
536 return await PrepareLocked(GenObj);
538 return await PrepareLocked(Object.GetType(), Object);
542 await synchObj.EndWrite();
546 private static async Task<Tuple<CollectionInformation, TypeInformation, GenericObject>> PrepareLocked(
GenericObject GenObj)
551 return new Tuple<CollectionInformation, TypeInformation, GenericObject>(CollectionInfo,
null, GenObj);
556 private static async Task<TypeInformation> GetTypeInfoLocked(Type T,
object Instance)
559 throw new Exception(
"Full text search module not started, or in the process of being stopped.");
561 if (types.TryGetValue(T, out TypeInformation Result))
564 TypeInfo TI = T.GetTypeInfo();
569 if (CollectionAttr is
null)
570 Result =
new TypeInformation(T, TI,
null,
null, CustomTokenizer,
null);
573 string CollectionName = CollectionAttr.Name;
574 bool DynamicIndex =
false;
577 if (!(SearchAttrs is
null))
593 IndexName = CollectionName;
604 Result =
new TypeInformation(T, TI, CollectionName, Info, CustomTokenizer, SearchAttrs);
607 await collectionInformation.
AddAsync(CollectionName, Info,
true);
610 Info.IndexForFullTextSearch =
true;
611 await collectionInformation.
AddAsync(CollectionName, Info,
true);
620 private static async Task<Tuple<CollectionInformation, TypeInformation, GenericObject>> PrepareLocked(Type T,
object Instance)
622 TypeInformation TypeInfo = await GetTypeInfoLocked(T, Instance);
623 if (!TypeInfo.HasCollection)
626 if (!TypeInfo.CollectionInformation?.IndexForFullTextSearch ??
false)
629 return new Tuple<CollectionInformation, TypeInformation, GenericObject>(TypeInfo.CollectionInformation, TypeInfo,
null);
640 internal static Keyword[] ParseKeywords(
string Search,
bool TreatKeywordsAsPrefixes)
642 return ParseKeywords(
Search, TreatKeywordsAsPrefixes,
true);
654 private static Keyword[] ParseKeywords(
string Search,
bool TreatKeywordsAsPrefixes,
657 List<Keyword> Result =
new List<Keyword>();
658 StringBuilder sb =
new StringBuilder();
660 bool Required =
false;
661 bool Prohibited =
false;
662 string Wildcard =
null;
667 foreach (
char ch
in Search.ToLower().Normalize(NormalizationForm.FormD))
669 UnicodeCategory Category = CharUnicodeInfo.GetUnicodeCategory(ch);
670 if (Category == UnicodeCategory.NonSpacingMark)
673 if (
char.IsLetterOrDigit(ch))
687 Add(
new RegexKeyword(Token), Result, ref Required, ref Prohibited);
699 Token = sb.ToString();
705 Result, ref Required, ref Prohibited);
714 Token = sb.ToString();
720 Result, ref Required, ref Prohibited);
725 else if (Type == 0 && (ch ==
'*' || ch ==
'%' || ch ==
'¤' || ch ==
'#'))
729 Wildcard =
new string(ch, 1);
735 Token = sb.ToString();
744 else if (TreatKeywordsAsPrefixes)
749 Add(
Keyword, Result, ref Required, ref Prohibited);
765 else if (ch ==
'"' && ParseQuotes)
767 else if (ch ==
'\'' && ParseQuotes)
774 Token = sb.ToString();
781 if (TreatKeywordsAsPrefixes)
796 Add(
Keyword, Result, ref Required, ref Prohibited);
799 return Result.ToArray();
802 private static void Add(
Keyword Keyword, List<Keyword> Result, ref
bool Required, ref
bool Prohibited)
831 internal static async Task<T[]> FullTextSearch<T>(
string IndexCollection,
836 if (MaxCount <= 0 || Keywords is
null)
839 int NrKeywords = Keywords.Length;
843 Keywords = (
Keyword[])Keywords.Clone();
844 Array.Sort(Keywords, orderOfProcessing);
846 StringBuilder sb =
new StringBuilder();
848 sb.Append(IndexCollection);
850 sb.Append(Order.ToString());
861 string Key = sb.ToString();
865 if (queryCache.
TryGetValue(Key, out QueryRecord QueryRecord))
867 FoundReferences = QueryRecord.FoundReferences;
868 Process = QueryRecord.Process;
874 await synchObj.BeginRead();
877 Index = await GetIndexLocked(IndexCollection,
false);
879 if (!(Index is
null))
895 await synchObj.EndRead();
900 await synchObj.BeginWrite();
903 Index = await GetIndexLocked(IndexCollection,
true);
918 await synchObj.EndWrite();
931 Array.Sort(FoundReferences, relevanceOrder);
935 Array.Sort(FoundReferences, occurrencesOrder);
939 Array.Sort(FoundReferences, newestOrder);
943 Array.Sort(FoundReferences, oldestOrder);
947 queryCache[Key] =
new QueryRecord()
949 FoundReferences = FoundReferences,
954 List<T> Result =
new List<T>();
1042 return Result.ToArray();
1051 private class QueryRecord
1059 Task.Run(() => this.ObjectDeleted(e));
1066 Tuple<CollectionInformation, TypeInformation, GenericObject> P = await Prepare(e.
Object);
1071 if (ObjectId is
null)
1081 await synchObj.BeginWrite();
1084 await RemoveTokensFromIndexLocked(Ref);
1088 await synchObj.EndWrite();
1095 catch (Exception ex)
1101 private static async Task RemoveTokensFromIndexLocked(
ObjectReference Ref)
1107 string Suffix =
" " + Token.
Block.ToString();
1116 int i = Array.IndexOf(References.ObjectReferences, Ref.
Index);
1120 int c = References.ObjectReferences.Length;
1121 ulong[] NewReferences =
new ulong[c - 1];
1122 uint[] NewCounts =
new uint[c - 1];
1123 DateTime[] NewTimestamps =
new DateTime[c - 1];
1127 Array.Copy(References.ObjectReferences, 0, NewReferences, 0, i);
1128 Array.Copy(References.Counts, 0, NewCounts, 0, i);
1129 Array.Copy(References.Timestamps, 0, NewTimestamps, 0, i);
1134 Array.Copy(References.ObjectReferences, i + 1, NewReferences, i, c - i - 1);
1135 Array.Copy(References.Counts, i + 1, NewCounts, i, c - i - 1);
1136 Array.Copy(References.Timestamps, i + 1, NewTimestamps, i, c - i - 1);
1139 References.ObjectReferences = NewReferences;
1140 References.Counts = NewCounts;
1141 References.Timestamps = NewTimestamps;
1160 Tuple<CollectionInformation, TypeInformation, GenericObject> P = await Prepare(Object);
1165 if (ObjectId is
null)
1169 TypeInformation TypeInfo = P.Item2;
1174 Tokens = await TypeInfo.Tokenize(Object, CollectionInfo.
Properties);
1182 if (AreSame(Tokens, Ref?.Tokens))
1187 await synchObj.BeginWrite();
1192 if (Tokens.Length == 0)
1198 IndexName = TypeInfo.GetIndexCollection(Object);
1202 ulong Index = await GetNextIndexNrLocked(IndexName);
1206 IndexCollection = IndexName,
1208 ObjectInstanceId = ObjectId,
1211 Indexed = DateTime.UtcNow
1214 await AddTokensToIndexLocked(Ref);
1221 await RemoveTokensFromIndexLocked(Ref);
1223 Ref.Tokens = Tokens;
1224 await AddTokensToIndexLocked(Ref);
1231 await synchObj.EndWrite();
1241 catch (Exception ex)
1249 int c = Tokens1?.Length ?? 0;
1250 int d = Tokens2?.Length ?? 0;
1257 for (i = 0; i < c; i++)
1259 if (!Tokens1[i].Equals(Tokens2[i]))
1270 IEnumerable<ObjectReference> ObjectsDeleted;
1279 await synchObj.BeginWrite();
1282 await RemoveTokensFromIndexLocked(Ref);
1286 await synchObj.EndWrite();
1294 while (!IsEmpty(ObjectsDeleted));
1296 catch (Exception ex)
1310 string[] Collections;
1312 await synchObj.BeginWrite();
1315 Index = await GetIndexLocked(IndexCollectionName,
true);
1318 Collections = await GetCollectionNamesLocked(IndexCollectionName);
1322 await synchObj.EndWrite();
1325 IEnumerable<ObjectReference> ObjectsDeleted;
1335 while (!IsEmpty(ObjectsDeleted));
1337 ReindexCollectionIteration Iteration =
new ReindexCollectionIteration();
1339 await
Database.Iterate<
object>(Iteration, Collections);
1341 return Iteration.NrObjectsProcessed;
1344 private static bool IsEmpty(IEnumerable<ObjectReference> Objects)
1354 public Task StartDatabase() => Task.CompletedTask;
1355 public Task EndDatabase() => Task.CompletedTask;
1356 public Task EndCollection() => Task.CompletedTask;
1357 public Task IncompatibleObject(
object ObjectId) => Task.CompletedTask;
1359 public long NrObjectsProcessed = 0;
1360 public int NrCollectionsProcessed = 0;
1362 public Task StartCollection(
string CollectionName)
1364 this.NrCollectionsProcessed++;
1365 return Task.CompletedTask;
1368 public async Task ProcessObject(
object Object)
1370 this.NrObjectsProcessed++;
1374 public Task ReportException(Exception Exception)
1377 return Task.CompletedTask;
1386 internal static void RegisterStopWords(params
string[] StopWords)
1388 Dictionary<string, bool> NewList =
new Dictionary<string, bool>();
1390 foreach (KeyValuePair<string, bool> P
in stopWords)
1391 NewList[P.Key] = P.Value;
1393 foreach (
string StopWord
in StopWords)
1394 NewList[StopWord] =
true;
1396 stopWords = NewList;
1404 internal static bool IsStopWord(
string StopWord)
1406 return stopWords.TryGetValue(StopWord, out
bool b) && b;
1416 public static async Task<TokenCount[]>
Tokenize(IEnumerable<object> Objects)
1431 public static async Task
Tokenize(IEnumerable<object> Objects,
1434 foreach (
object Object
in Objects)
1441 Type T = Object2.GetType();
1447 Found = tokenizers.TryGetValue(T, out Tokenizer);
1456 tokenizers[T] = Tokenizer;
1460 if (Tokenizer is
null)
1462 Tuple<CollectionInformation, TypeInformation, GenericObject> P = await Prepare(Object2);
1467 if (ObjectId is
null)
1471 TypeInformation TypeInfo = P.Item2;
1475 await TypeInfo.Tokenize(Object2, Process, CollectionInfo.
Properties);
1480 await Tokenizer.
Tokenize(Object2, Process);
1482 Process.DocumentIndexOffset++;
1486 private static readonly Dictionary<Type, ITokenizer> tokenizers =
new Dictionary<Type, ITokenizer>();
1488 private void Types_OnInvalidated(
object Sender, EventArgs e)
1504 LinkedList<object> Values = await GetValues(Obj, Properties);
1506 if (Values.First is
null)
1521 LinkedList<object> Values = await GetValues(Obj, Properties);
1523 if (!(Values.First is
null))
1535 LinkedList<object> Values =
new LinkedList<object>();
1542 Value = await Property.
GetValue(Obj);
1543 if (!(Value is
null))
1544 Values.AddLast(Value);
1559 internal static async Task<FolderIndexationStatistics> IndexFolder(
string IndexCollection,
string Folder,
bool Recursive,
1560 params
string[] ExcludeSubfolders)
1562 if (
string.IsNullOrEmpty(IndexCollection))
1563 throw new ArgumentException(
"Empty index.", nameof(IndexCollection));
1565 if (
string.IsNullOrEmpty(Folder))
1566 throw new ArgumentException(
"Empty folder.", nameof(Folder));
1568 Folder = Path.GetFullPath(Folder);
1569 if (!Directory.Exists(Folder))
1570 throw new ArgumentException(
"Folder does not exist.", nameof(Folder));
1572 if (Folder[Folder.Length - 1] != Path.DirectorySeparatorChar)
1573 Folder += Path.DirectorySeparatorChar;
1575 string[] FileNames = Directory.GetFiles(Folder,
"*.*", Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
1576 Dictionary<CaseInsensitiveString, FileReference> References =
new Dictionary<CaseInsensitiveString, FileReference>();
1580 if (!(ExcludeSubfolders is
null))
1582 ExcludeSubfolders = (
string[])ExcludeSubfolders.Clone();
1583 c = ExcludeSubfolders.Length;
1585 for (i = 0; i < c; i++)
1587 ExcludeSubfolders[i] = Path.GetFullPath(ExcludeSubfolders[i]);
1588 d = ExcludeSubfolders[i].Length;
1590 if (d == 0 || ExcludeSubfolders[i][d - 1] != Path.DirectorySeparatorChar)
1591 ExcludeSubfolders[i] += Path.DirectorySeparatorChar;
1601 References[Reference.
FileName] = Reference;
1603 foreach (
string FileName
in FileNames)
1605 if (!(ExcludeSubfolders is
null))
1607 bool Exclude =
false;
1609 foreach (
string s
in ExcludeSubfolders)
1611 if (FileName.StartsWith(s))
1627 DateTime TP = File.GetLastWriteTimeUtc(FileName);
1629 if (References.TryGetValue(FileName, out
FileReference Ref))
1631 References.Remove(FileName);
1633 if (Ref.Timestamp == TP)
1646 FileName = FileName,
1647 IndexCollection = IndexCollection,
1674 internal static async Task<bool> IndexFile(
string IndexCollection,
string FileName)
1676 FileName = Path.GetFullPath(FileName);
1686 if (File.Exists(FileName))
1688 DateTime TP = File.GetLastWriteTimeUtc(FileName);
1690 if (ReferenceInDB is
null)
1694 FileName = FileName,
1695 IndexCollection = IndexCollection,
1708 ReferenceInDB.Timestamp = TP;
1714 else if (ReferenceInDB is
null)
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
This attribute defines the name of the collection that will house objects of this type.
Event arguments for collection events.
string Collection
Collection
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static Task< IPersistentDictionary > GetDictionary(string Collection)
Gets a persistent dictionary containing objects in a collection.
static Task< object > TryGetObjectId(object Object)
Tries to get the Object ID of an object, if it exists.
static string WildcardToRegex(string s, string Wildcard)
Converts a wildcard string to a regular expression string.
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
static Task< object > TryLoadObject(string CollectionName, object ObjectId)
Tries to load an object given its Object ID ObjectId and its collection name CollectionName .
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field matching a given regular expression.
Contains information about a collection, in relation to full-text-search.
bool IndexForFullTextSearch
If collection should be indexed.
bool AddIndexableProperties(params PropertyDefinition[] Properties)
Adds properties for full-text-search indexation.
PropertyDefinition[] Properties
Properties to index
string CollectionName
Collection Name
string IndexCollectionName
Index Collection Name
bool RemoveIndexableProperties(params PropertyDefinition[] Properties)
Removes properties from full-text-search indexation.
Contains a reference to an indexed file.
DateTime Timestamp
When object was indexed.
CaseInsensitiveString FileName
Name of collection hosting object.
Contains statistics about a files folder (re)indexation procedure.
int TotalChanges
Total number of files changed in the index.
int NrDeleted
Number of files deleted from the index.
int NrUpdated
Number of files updated in the index.
int NrAdded
Number of files added to the index.
int NrFiles
Number of files processed.
This attribute defines that objects of this type should be indexed in the full-text-search index.
bool DynamicIndexCollection
If the index collection is dynamic (i.e. depends on object instance).
string GetIndexCollection(object Reference)
Name of full-text-search index collection.
Full-text search module, controlling the life-cycle of the full-text-search engine.
static async Task ProcessObjectUpdate(object Object)
Processes an object that has been updated.
static async Task< TokenCount[]> Tokenize(IEnumerable< object > Objects)
Tokenizes a set of objects using available tokenizers. Tokenizers are classes with a default contruct...
async Task Start()
Starts the module.
static async Task< long > ReindexCollection(string IndexCollectionName)
Reindexes the full-text-search index for a database collection.
static async Task< string[]> GetCollectionNames(string IndexCollectionName)
Gets the database collections that get indexed into a given index colltion.
async Task Stop()
Stops the module.
FullTextSearchModule()
Full-text search module, controlling the life-cycle of the full-text-search engine.
static async Task Tokenize(IEnumerable< object > Objects, TokenizationProcess Process)
Tokenizes a set of objects using available tokenizers. Tokenizers are classes with a default contruct...
static async Task< Dictionary< string, string[]> > GetCollectionNames()
Gets the database collections that get indexed into a given index colltion.
Abstract base class for keywords.
virtual async Task< bool > Process(SearchProcess Process)
Processes the keyword in a search process.
virtual bool Ignore
If keyword should be ignored.
abstract new string ToString()
Orders strings in descending length order
Represents a plain text keyword.
Represents a prohibited keyword.
Represents a wildcard keyword.
Represents a required keyword.
Contains information about a search process.
async Task< ObjectReference > TryGetObjectReference(ulong ObjectIndex, bool CanLoadFromDatabase)
Tries to get an object reference.
Dictionary< ulong, MatchInformation > ReferencesByObject
References found.
Represents a sequence of keywords.
Represents a wildcard keyword.
Event arguments for object reference events.
Contains a reference to an indexed object.
object ObjectInstanceId
Object ID of object instance.
TokenCount[] Tokens
Token count in document.
string Collection
Name of collection hosting object.
ObjectReference()
Contains a reference to an indexed object.
string IndexCollection
Collection of full-text-search index.
ulong Index
Reference number to use in full-text-index.
Contains matching information about a document in a search.
Orders entries from newest to oldest.
Orders entries based on occurrences of keywords.
Orders entries from oldest to newest.
Orders entries based on relevance.
Defines an indexable property.
async Task< object > GetValue(object Instance)
Gets the object to index.
Static class for access to Full-Text-Search
Represents a token and a corresponding occurrence count.
uint Block
Reference is stored in this block in the full-text-search index.
override string ToString()
Object.ToString()
uint[] DocIndex
Index inside document of each occurrence.
Contains a sequence of object references that include the token in its indexed text properties.
uint[] Counts
Token counts for respective object reference.
const int MaxReferences
Maximum amount of references in a block (100).
Tokenizes files via FileReference object references.
static bool HasTokenizer(string FileName)
Checks if a file has a file tokenizer associated with it.
Contains information about a tokenization process.
TokenCount[] ToArray()
Generates an array of token counts.
Event arguments for database object events.
Generic object. Contains a sequence of properties.
string CollectionName
Collection name.
Implements an in-memory cache.
void Dispose()
IDisposable.Dispose
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
void Clear()
Clears the cache.
Static class that dynamically manages types and interfaces available in the runtime environment.
Represents an object that allows single concurrent writers but multiple concurrent readers....
Base class for all nodes in a parsed script tree.
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
Interface for full-text-search tokenizers
Task Tokenize(object Value, TokenizationProcess Process)
Tokenizes an object.
Persistent dictionary that can contain more entries than possible in the internal memory.
Task< KeyValuePair< bool, object > > TryGetValueAsync(string key)
Gets the value associated with the specified key.
Task< object[]> GetValuesAsync()
Gets all values.
Task AddAsync(string key, object value)
Adds an element with the provided key and value to the System.Collections.Generic....
Task ClearAsync()
Clears the dictionary.
Interface for iterations of database contents.
Interface for late-bound modules loaded at runtime.
FullTextSearchOrder
Order in which results are returned.
PaginationStrategy
How pagination in full-text-searches should be handled.