SearchBox/SearchBox/InvertedIndex.cs

67 lines
1.9 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace LibSearchBox
{
public class InvertedIndex
{
// 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()
{
}
public bool AddIndex(int pageId, Index newIndex)
{
foreach (KeyValuePair<string, List<int>> token in newIndex)
{
if (!invertedIndex.ContainsKey(token.Key) &&
!invertedIndex.TryAdd(token.Key, new ConcurrentDictionary<int, List<int>>()))
return false;
if (!invertedIndex[token.Key].TryAdd(pageId, token.Value))
return false;
}
return true;
}
public bool RemoveIndex(int pageId, Index oldIndex)
{
foreach (string token in oldIndex.Tokens()) {
if (!invertedIndex.ContainsKey(token) || !invertedIndex[token].ContainsKey(pageId)) continue;
if (!invertedIndex[token].TryRemove(pageId, out List<int> noop))
return false;
}
return false;
}
public bool ReplaceIndex(int pageId, Index oldIndex, Index newIndex)
{
if (!RemoveIndex(pageId, oldIndex)) return false;
if (!AddIndex(pageId, newIndex)) return false;
return true;
}
public bool RemoveById(int pageId)
{
foreach (KeyValuePair<string, ConcurrentDictionary<int, List<int>>> pair in invertedIndex) {
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;
}
public ConcurrentDictionary<int, List<int>> Query(string normalisedToken)
{
invertedIndex.TryGetValue(normalisedToken, out ConcurrentDictionary<int, List<int>> result);
return result;
}
}
}