Compare commits
2 Commits
959aa219ce
...
7bef5d9b17
Author | SHA1 | Date |
---|---|---|
Starbeamrainbowlabs | 7bef5d9b17 | |
Starbeamrainbowlabs | ddd94b3641 |
|
@ -6,6 +6,7 @@ using Newtonsoft.Json;
|
|||
|
||||
using LibSearchBox;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace SearchBoxCLI
|
||||
{
|
||||
|
@ -38,8 +39,12 @@ namespace SearchBoxCLI
|
|||
List<string> extras = new List<string>();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
switch (args[i].TrimStart("-".ToCharArray()))
|
||||
{
|
||||
if (!args[i].StartsWith("-")) {
|
||||
extras.Add(args[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (args[i].TrimStart("-".ToCharArray())) {
|
||||
case "s":
|
||||
case "source":
|
||||
string sourceFilename = args[++i];
|
||||
|
@ -79,7 +84,7 @@ namespace SearchBoxCLI
|
|||
}
|
||||
if (extras.Count < 1) return HandleHelp();
|
||||
string modeText = extras.First(); extras.RemoveAt(0);
|
||||
Mode = (OperatingModes)Enum.Parse(typeof(OperatingModes), modeText);
|
||||
Mode = (OperatingModes)Enum.Parse(typeof(OperatingModes), modeText, true);
|
||||
|
||||
switch (Mode) {
|
||||
case OperatingModes.Index: return HandleIndex();
|
||||
|
@ -126,6 +131,10 @@ namespace SearchBoxCLI
|
|||
Console.Error.WriteLine("Error: The document name must be specified when reading from stdin!");
|
||||
return 1;
|
||||
}
|
||||
if (SearchIndexFilepath == string.Empty) {
|
||||
Console.Error.WriteLine("Error: No search index file path specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@ namespace LibSearchBox
|
|||
public class DocumentMeta
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public List<string> Tags { get; private set; }
|
||||
public List<string> Tags { get; private set; } = new List<string>();
|
||||
|
||||
public DocumentMeta(string inTitle, IEnumerable<string> inTags)
|
||||
{
|
||||
Title = inTitle;
|
||||
Tags = new List<string>(inTags);
|
||||
if (inTags != null)
|
||||
Tags.AddRange(inTags);
|
||||
}
|
||||
|
||||
public void ReplaceTags(IEnumerable<string> newTags)
|
||||
|
@ -19,5 +20,15 @@ namespace LibSearchBox
|
|||
Tags.Clear();
|
||||
Tags.AddRange(newTags);
|
||||
}
|
||||
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[DocumentMeta Title={Title}, Tags={string.Join(",", Tags)}]";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Stackoverflow.Utilities;
|
||||
|
||||
namespace LibSearchBox
|
||||
|
@ -12,10 +14,34 @@ namespace LibSearchBox
|
|||
private int nextId = 0;
|
||||
public BiDictionary<int, string> map = new BiDictionary<int, string>();
|
||||
|
||||
public Dictionary<int, string> MapOut {
|
||||
get {
|
||||
Dictionary<int, string> result = new Dictionary<int, string>();
|
||||
foreach (BiDictionary<int, string>.Pair pair in map)
|
||||
result.Add(pair.First, pair.Second);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public IdMap()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public void Import(Dictionary<int, string> inMap, bool clearOld = true) {
|
||||
// Clear out the old map, if any
|
||||
if(clearOld) map.Clear();
|
||||
|
||||
// Import the new records
|
||||
foreach (KeyValuePair<int, string> pair in inMap)
|
||||
map.Add(pair.Key, pair.Value);
|
||||
|
||||
// Calculate the next id
|
||||
// FUTURE: Store & retrieve this via JSON
|
||||
nextId = map.Max((pair) => pair.First) + 1;
|
||||
}
|
||||
|
||||
|
||||
public int GetId(string pageName)
|
||||
{
|
||||
// Perform unicode normalization
|
||||
|
|
|
@ -6,7 +6,8 @@ namespace LibSearchBox
|
|||
{
|
||||
public class InvertedIndex
|
||||
{
|
||||
private ConcurrentDictionary<string, ConcurrentDictionary<int, List<int>>> invertedIndex = new ConcurrentDictionary<string, ConcurrentDictionary<int, List<int>>>();
|
||||
// Gotta be public to allow Newtonsoft.JSON to do it's job. Don't interact with it directly!
|
||||
public ConcurrentDictionary<string, ConcurrentDictionary<int, List<int>>> invertedIndex = new ConcurrentDictionary<string, ConcurrentDictionary<int, List<int>>>();
|
||||
|
||||
public InvertedIndex()
|
||||
{
|
||||
|
@ -28,8 +29,7 @@ namespace LibSearchBox
|
|||
|
||||
public bool RemoveIndex(int pageId, Index oldIndex)
|
||||
{
|
||||
foreach (string token in oldIndex.Tokens())
|
||||
{
|
||||
foreach (string token in oldIndex.Tokens()) {
|
||||
if (!invertedIndex.ContainsKey(token) || !invertedIndex[token].ContainsKey(pageId)) continue;
|
||||
|
||||
if (!invertedIndex[token].TryRemove(pageId, out List<int> noop))
|
||||
|
@ -51,6 +51,8 @@ namespace LibSearchBox
|
|||
if (!pair.Value.ContainsKey(pageId)) continue;
|
||||
if (!pair.Value.TryRemove(pageId, out List<int> noop))
|
||||
return false;
|
||||
if (pair.Value.Count == 0 && !invertedIndex.TryRemove(pair.Key, out var noopAgain))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace LibSearchBox
|
||||
{
|
||||
public class SearchBoxException : Exception { public SearchBoxException(string message) : base(message) { } }
|
||||
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class SearchBox
|
||||
{
|
||||
private IdMap idMap = new IdMap();
|
||||
private InvertedIndex index = new InvertedIndex();
|
||||
private ConcurrentDictionary<int, DocumentMeta> metaTable = new ConcurrentDictionary<int, DocumentMeta>();
|
||||
|
||||
[JsonProperty("ids")]
|
||||
public Dictionary<int, string> IdMap {
|
||||
get {
|
||||
Dictionary<int, string> result = idMap.MapOut;
|
||||
if (result.Count == 0) return null;
|
||||
return result;
|
||||
}
|
||||
set {
|
||||
if (value == null) return;
|
||||
idMap.Import(value);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public ConcurrentDictionary<int, DocumentMeta> metaTable = new ConcurrentDictionary<int, DocumentMeta>();
|
||||
[JsonProperty]
|
||||
public InvertedIndex index = new InvertedIndex();
|
||||
|
||||
public SearchBox()
|
||||
{
|
||||
|
@ -21,6 +39,7 @@ namespace LibSearchBox
|
|||
{
|
||||
DocumentMeta info = new DocumentMeta(title, tags);
|
||||
int id = idMap.GetId(info.Title);
|
||||
metaTable.AddOrUpdate(id, info, (key, oldValue) => info);
|
||||
Index upsideIndex = new Index(content);
|
||||
index.AddIndex(id, upsideIndex);
|
||||
}
|
||||
|
@ -33,7 +52,7 @@ namespace LibSearchBox
|
|||
|
||||
Index oldIndex = new Index(oldContent), newIndex = new Index(newContent);
|
||||
if (!index.ReplaceIndex(id, oldIndex, newIndex))
|
||||
throw new Exception($"Error: Failed to replace index for document with title {title}.");
|
||||
throw new SearchBoxException($"Error: Failed to replace index for document with title {title}.");
|
||||
}
|
||||
|
||||
public void RemoveDocument(string title)
|
||||
|
|
Loading…
Reference in New Issue