// Returns one of: // - Document and Key, Key may be missing // - Array and Index, Index is always valid public static ResolvedDocumentPath ResolvePath(this BsonDocument that, string path, ResolvePathOptions options = ResolvePathOptions.None) { var r = new ResolvedDocumentPath(); if (path.IndexOf('.') < 0) { r.Document = that; r.Key = path; return(r); } var document = that; var keys = path.Split('.'); int last = keys.Length - 1; for (int i = 0; i <= last; ++i) { var key = keys[i]; if (i == last) { r.Document = document; r.Key = key; return(r); } BsonValue value; if (!document.TryGetValue(key, out value)) { return(null); } if (value.BsonType == BsonType.Document) { document = value.AsBsonDocument; continue; } int arrayIndex; if (value.BsonType != BsonType.Array || !int.TryParse(keys[i + 1], out arrayIndex)) { return(null); } if ((options & ResolvePathOptions.NoArray) != ResolvePathOptions.None) { throw new InvalidOperationException("Array indexes are not supported."); } //_140322_065506 if (arrayIndex < 0) { if ((options & ResolvePathOptions.YesNegativeIndex) != ResolvePathOptions.None) { return(null); } throw new InvalidOperationException(string.Format(null, "Invalid negative array index in ({0}).", path)); } var array = value.AsBsonArray; if (arrayIndex >= array.Count) { return(null); } if (i == last - 1) { r.Array = array; r.Index = arrayIndex; return(r); } var value2 = array[arrayIndex]; if (value2.BsonType != BsonType.Document) { return(null); } document = value2.AsBsonDocument; ++i; } return(null); }
public static ResolvedDocumentPath EnsurePath(this BsonDocument that, string path) { var r = new ResolvedDocumentPath(); if (path.IndexOf('.') < 0) { r.Document = that; r.Key = path; return(r); } var document = that; var keys = path.Split('.'); int last = keys.Length - 1; for (int i = 0; i <= last; ++i) { var key = keys[i]; if (i == last) { r.Document = document; r.Key = key; return(r); } BsonValue value; if (!document.TryGetValue(key, out value)) { var newDocument = new BsonDocument(); document.Add(key, newDocument); document = newDocument; continue; } if (value.BsonType == BsonType.Document) { document = value.AsBsonDocument; continue; } int arrayIndex; if (value.BsonType == BsonType.Array && int.TryParse(keys[i + 1], out arrayIndex)) { var array = value.AsBsonArray; if (i == last - 1) { r.Array = array; r.Index = arrayIndex; return(r); } if (!array.InsertOutOfRange(arrayIndex, () => document = new BsonDocument())) { var value2 = array[arrayIndex]; if (value2.BsonType != BsonType.Document) { throw new InvalidOperationException(string.Format(null, "Array item at ({0}) in ({1}) is not a document.", arrayIndex, path)); } document = value2.AsBsonDocument; } ++i; continue; } throw new InvalidOperationException(string.Format(null, "Field ({0}) in ({1}) is not a document.", key, path)); } return(null); }