/// <summary> /// Returns all values from array according index. If index are MaxValue, return all values /// </summary> public static IEnumerable <BsonValue> Array(IEnumerable <BsonValue> values, int index, BsonExpression expr, BsonDocument root) { foreach (var value in values) { if (value.IsArray) { var arr = value.AsArray; // [<expr>] - index are an expression if (expr.Source != null) { foreach (var item in arr) { // execute for each child value and except a first bool value (returns if true) var c = expr.Execute(root, item, true).First(); if (c.IsBoolean && c.AsBoolean == true) { // fill destroy action to remove value from parent array item.Destroy = () => arr.Remove(item); yield return(item); } } } // [*] - index are all values else if (index == int.MaxValue) { foreach (var item in arr) { // fill destroy action to remove value from parent array item.Destroy = () => arr.Remove(item); yield return(item); } } // [n] - fixed index else { var idx = index < 0 ? arr.Count + index : index; if (arr.Count > idx) { var item = arr[idx]; // fill destroy action to remove value from parent array item.Destroy = () => arr.Remove(item); yield return(item); } } } } }
/// <summary> /// Create a new index (or do nothing if already exists) to a collection/field /// </summary> public bool EnsureIndex(string collection, string field, string expression, 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 } if (expression != null && expression.Length > 200) { throw new ArgumentException("expression is limited in 200 characters", "expression"); } return(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.Expression = expression ?? "$." + field; index.Unique = unique; _log.Write(Logger.Command, "create index on '{0}' :: {1} unique: {2}", collection, index.Expression, 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 BsonExpression(index.Expression); // get values from expression in 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> /// Get an IEnumerable of values from a json-like path inside document. Use BsonExpression to parse this path /// </summary> public IEnumerable <BsonValue> Get(string path, bool includeNullIfEmpty = false) { var expr = new BsonExpression(new StringScanner(path), true, true); return(expr.Execute(this, includeNullIfEmpty)); }