public IEnumerable <KeyValuePair <string, IJsonValue> > FindIndexedObjects(IJsonValue obj) { HashSet <string> keys = null; var indexPaths = new HashSet <string>(); foreach (var g in from indexValue in GetObjectIndexValues(obj) group indexValue by indexValue.Item1 into g select g) { indexPaths.Add(g.Key.MemberPath); HashSet <string> keysForThisIndex = null; foreach (var tuple in g) { if (keysForThisIndex == null) { keysForThisIndex = new HashSet <string>(g.Key.FindKeys(tuple.Item2)); } else { keysForThisIndex.IntersectWith(g.Key.FindKeys(tuple.Item2)); } if (keysForThisIndex.Count == 0) { return(Enumerable.Empty <KeyValuePair <string, IJsonValue> >()); } } if (keys == null) { keys = keysForThisIndex; } else { keys.IntersectWith(keysForThisIndex); } if (keys.Count == 0) { return(Enumerable.Empty <KeyValuePair <string, IJsonValue> >()); } } if (keys == null) { // table scan var filter = new JsonFilter(obj.JsonPathValues()); return(from rec in MasterTable.Scan() where filter.Matches(rec.Value) select rec); } else { var filter = new JsonFilter(obj.JsonPathValues().Where(pv => !indexPaths.Contains(pv.Path.Path))); return(from key in keys from rec in MasterTable.Find(key) where filter.Matches(rec.Value) select rec); } }
public bool EnsureIndex(IndexDefinition indexDefinition) { // Try to not rebuild index, so we check if there exists an equal defintion already IndexWrapper existing; if (IndexCache.TryGetValue(indexDefinition.Path, out existing)) { if (indexDefinition.Options.Equals(existing.IndexDefinition.Options)) { // phew, existing index was already matching. bail out return(false); } DropIndex(indexDefinition.Path); } // An index can not both exclude certain values and at the same time include certain values var hasIncludeValues = (indexDefinition.Options.IncludeValues != null) && (indexDefinition.Options.IncludeValues.Length > 0); var hasExcludeValues = (indexDefinition.Options.ExcludeValues != null) && (indexDefinition.Options.ExcludeValues.Length > 0); if (hasIncludeValues && hasExcludeValues) { throw new KiwiDbException("An index can not have an exclusion list and an inclusion list at the same time."); } var index = new IndexWrapper(this, indexDefinition) { IsChanged = true }; IndexCache.Add(indexDefinition.Path, index); Insert(indexDefinition.Path, JSON.FromObject(indexDefinition)); // rebuild index foreach (var record in MasterTable.Scan()) { UpdateIndex(record.Key, null, record.Value); } return(true); }