public static BsonDocument Deserialize(byte[] bson, bool utcDate = true) { if (bson == null || bson.Length == 0) { throw new ArgumentNullException(nameof(bson)); } return(BsonReader.Deserialize(bson, utcDate)); }
public static BsonDocument Deserialize(ArraySegment <byte> buffer, bool utcDate = true) { if (buffer == null || buffer.Count == 0) { throw new ArgumentNullException(nameof(buffer)); } return(BsonReader.Deserialize(buffer, utcDate)); }
/// <summary> /// Count all nodes from a query execution - do not deserialize documents to count. If query is null, use Collection counter variable /// </summary> public long Count(string collection, Query query = null) { if (collection.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(collection)); } var col = this.GetCollectionPage(collection, false); if (col == null) { return(0); } if (query == null) { return(col.DocumentCount); } // run query in this collection var nodes = query.Run(col, _indexer); if (query.UseFilter) { // count distinct documents return(nodes .Select(x => BsonReader.Deserialize(_data.Read(x.DataBlock)).AsDocument) .Where(x => query.FilterDocument(x)) .Distinct() .LongCount()); } else { // count distinct nodes based on DataBlock return(nodes .Select(x => x.DataBlock) .Distinct() .LongCount()); } }
/// <summary> /// Check if has at least one node in a query execution - do not deserialize documents to check /// </summary> public bool Exists(string collection, Query query) { if (collection.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(collection)); } if (query == null) { throw new ArgumentNullException(nameof(query)); } var col = this.GetCollectionPage(collection, false); if (col == null) { return(false); } // run query in this collection var nodes = query.Run(col, _indexer); if (query.UseFilter) { // check if has at least first document return(nodes .Select(x => BsonReader.Deserialize(_data.Read(x.DataBlock)).AsDocument) .Where(x => query.FilterDocument(x)) .Any()); } else { var first = nodes.FirstOrDefault(); // check if has at least first node return(first != null); } }
/// <summary> /// Implements delete based on a query result /// </summary> public int Delete(string collection, Query query) { if (collection.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(collection)); } if (query == null) { throw new ArgumentNullException(nameof(query)); } return(this.Transaction <int>(collection, false, (col) => { if (col == null) { return 0; } _log.Write(Logger.COMMAND, "delete documents in '{0}'", collection); var nodes = query.Run(col, _indexer); _log.Write(Logger.QUERY, "{0} :: {1}", collection, query); var count = 0; foreach (var node in nodes) { // checks if cache are full _trans.CheckPoint(); // if use filter need deserialize document if (query.UseFilter) { var buffer = _data.Read(node.DataBlock); var doc = BsonReader.Deserialize(buffer).AsDocument; if (query.FilterDocument(doc) == false) { continue; } } _log.Write(Logger.COMMAND, "delete document :: _id = {0}", node.Key.RawValue); // get all indexes nodes from this data block var allNodes = _indexer.GetNodeList(node, true).ToArray(); // lets remove all indexes that point to this in dataBlock foreach (var linkNode in allNodes) { var index = col.Indexes[linkNode.Slot]; _indexer.Delete(index, linkNode.Position); } // remove object data _data.Delete(col, node.DataBlock); count++; } return count; })); }
/// <summary> /// Create a new index (or do nothing if already exists) to a collection/field /// </summary> public bool EnsureIndex(string collection, string field, bool unique = false) { if (collection.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(collection)); } if (!CollectionIndex.IndexPattern.IsMatch(field)) { throw new ArgumentException("Invalid field format pattern: " + CollectionIndex.IndexPattern.ToString(), "field"); } if (field == "_id") { return(false); // always exists } return(this.Transaction <bool>(collection, true, (col) => { // check if index already exists var current = col.GetIndex(field); // if already exists, just exit if (current != null) { // do not test any difference between current index and new defition return false; } // create index head var index = _indexer.CreateIndex(col); index.Field = field; index.Unique = unique; _log.Write(Logger.COMMAND, "create index on '{0}' :: {1} unique: {2}", collection, index.Field, unique); // read all objects (read from PK index) foreach (var pkNode in new QueryAll("_id", Query.Ascending).Run(col, _indexer)) { // read binary and deserialize document var buffer = _data.Read(pkNode.DataBlock); var doc = BsonReader.Deserialize(buffer).AsDocument; var expr = new BsonFields(index.Field); // get value from document var keys = expr.Execute(doc, true); // adding index node for each value foreach (var key in keys) { // insert new index node var node = _indexer.AddNode(index, key, pkNode); // link index node to datablock node.DataBlock = pkNode.DataBlock; } // check memory usage _trans.CheckPoint(); } return true; })); }
/// <summary> /// Fetch documents from enumerator and add to buffer. If cache recycle, stop read to execute in another read /// </summary> public void Fetch(TransactionService trans, DataService data) { // empty document buffer this.Documents.Clear(); // while until must cache not recycle while (trans.CheckPoint() == false) { // read next node this.HasMore = _nodes.MoveNext(); // if finish, exit loop if (this.HasMore == false) { return; } // if run ONLY under index, skip/limit before deserialize if (_query.UseIndex && _query.UseFilter == false) { if (--_skip >= 0) { continue; } if (--_limit <= -1) { this.HasMore = false; return; } } // get current node var node = _nodes.Current; // read document from data block var buffer = data.Read(node.DataBlock); var doc = BsonReader.Deserialize(buffer).AsDocument; // if need run in full scan, execute full scan and test return if (_query.UseFilter) { // execute query condition here - if false, do not add on final results if (_query.FilterDocument(doc) == false) { continue; } // implement skip/limit after deserialize in full scan if (--_skip >= 0) { continue; } if (--_limit <= -1) { this.HasMore = false; return; } } // increment position cursor _position++; // avoid lock again just to check limit if (_limit == 0) { this.HasMore = false; } this.Documents.Add(doc); } }