예제 #1
0
        public WriteConcernResult Remove(IMongoQuery query, RemoveFlags flags, WriteConcern writeConcern, bool needResult)
        {
            var predicate = QueryCompiler.GetFunction(query.ToBsonDocument());

            int documentsAffected = 0;

            for (int i = 0; i < Documents.Count; ++i)
            {
                if (!predicate(Documents[i]))
                {
                    continue;
                }

                RemoveDocumentAt(i);

                ++documentsAffected;

                if ((flags & RemoveFlags.Single) > 0)
                {
                    break;
                }

                --i;
            }

            return(needResult ? new WriteConcernResult(NewResponse(documentsAffected, false, null, null)) : null);
        }
예제 #2
0
        public object FindAndRemoveAs(Type documentType, IMongoQuery query, IMongoSortBy sortBy)
        {
            foreach (var document in QueryCompiler.Query(Documents, Documents2, query, sortBy, 0, 0))
            {
                RemoveDocument(document);
                return(BsonSerializer.Deserialize(document, documentType));
            }

            return(null);
        }
예제 #3
0
        public IEnumerable <object> FindAs(Type documentType, IMongoQuery query, QueryFlags modes, IMongoSortBy sortBy, int skip, int first, IMongoFields fields)
        {
            var iter = QueryCompiler.Query(Documents, Documents2, query, sortBy, skip, first);

            if (fields == null)
            {
                return(iter.Select(x => BsonSerializer.Deserialize(x, documentType)));
            }

            var project = FieldCompiler.GetFunction(fields);

            return(iter.Select(project).Select(x => BsonSerializer.Deserialize(x, documentType)));
        }
예제 #4
0
        public object FindAndModifyAs(Type documentType, IMongoQuery query, IMongoSortBy sortBy, IMongoUpdate update, IMongoFields fields, bool returnNew, bool upsert, out UpdateResult result)
        {
            foreach (var document in QueryCompiler.Query(Documents, Documents2, query, sortBy, 0, 0))
            {
                // if old is needed then deep(!) clone before update //_131103_185751
                BsonDocument output = null;
                if (!returnNew)
                {
                    output = document.DeepClone().AsBsonDocument;
                }

                UpdateDocument(document, UpdateCompiler.GetFunction((IConvertibleToBsonDocument)update, null, false));

                if (returnNew)
                {
                    output = document;
                }

                // project
                if (fields != null)
                {
                    var project = FieldCompiler.GetFunction(fields);
                    output = project(output);
                }

                // if old is needed then return it as already deep cloned
                result = new SimpleUpdateResult(1, true);
                if (!returnNew && documentType == typeof(Dictionary))
                {
                    return(new Dictionary(output));
                }
                else
                {
                    // deserialize to required type
                    return(BsonSerializer.Deserialize(output, documentType));
                }
            }

            // not found, insert
            if (upsert)
            {
                var document = InsertNewDocument(query, update);

                result = new SimpleUpdateResult(1, false);
                return(returnNew ? BsonSerializer.Deserialize(document, documentType) : null);
            }

            result = new SimpleUpdateResult(0, false);
            return(null);
        }
예제 #5
0
        static Expression PushEachExpression(Expression that, Expression field, BsonDocument document)
        {
            int       position = -1;
            BsonArray each = null;
            BsonValue sort = null, slice = null;

            foreach (var e in document.Elements)
            {
                //TODO
                switch (e.Name)
                {
                case "$each":
                    if (e.Value.BsonType != BsonType.Array)
                    {
                        throw new ArgumentException("Push all/each value must be array.");
                    }
                    each = e.Value.AsBsonArray;
                    break;

                case "$sort":
                    sort = e.Value;
                    break;

                case "$slice":
                    if (!e.Value.IsNumeric)
                    {
                        throw new ArgumentException("$slice must be a numeric value.");
                    }
                    slice = e.Value;
                    break;

                case "$position":
                    if (!e.Value.IsNumeric)
                    {
                        throw new ArgumentException("$position must be a numeric value.");
                    }
                    position = e.Value.ToInt32();
                    if (position < 0)
                    {
                        throw new ArgumentException("$position must not be negative.");
                    }
                    break;

                default:
                    throw new ArgumentException(string.Format(null, "Unrecognized clause in $push: ({0}).", e.Name));
                }
            }

            if (sort != null)
            {
                switch (sort.BsonType)
                {
                case BsonType.Int32:
                    switch (sort.AsInt32)
                    {
                    case 1:
                        each = new BsonArray(each.OrderBy(x => x)); break;                                         //TODO comparer?

                    case -1:
                        each = new BsonArray(each.OrderByDescending(x => x)); break;                                         //TODO comparer?

                    default:
                        throw new ArgumentException("Numeric $sort value must be either 1 or -1.");
                    }
                    break;

                case BsonType.Document:
                    //TODO not needed in Mongo v2.6
                    foreach (var d1 in each)
                    {
                        if (d1.BsonType != BsonType.Document)
                        {
                            throw new ArgumentException("$sort requires $each to be an array of objects.");
                        }
                    }

                    each = new BsonArray(QueryCompiler.Query(each.Cast <BsonDocument>(), null, null, new SortByDocument(sort.AsBsonDocument), 0, 0));
                    break;

                default:
                    throw new ArgumentException("$sort value must be 1, -1, or a document.");
                }
            }

            if (slice != null)
            {
                each = each.Slice(0, slice.ToInt32());
            }

            return(Expression.Call(that, GetMethod("PushAll"), Data, field,
                                   Expression.Constant(each, typeof(BsonValue)), Expression.Constant(position, typeof(int))));
        }
예제 #6
0
        static void Pull(BsonDocument document, string name, BsonValue value, bool all)
        {
            var r = document.ResolvePath(name);

            if (r == null)
            {
                return;                 //_140322_065637
            }
            BsonValue vArray;

            if (r.Array != null)
            {
                vArray = r.Array[r.Index];
            }
            else if (!r.Document.TryGetValue(r.Key, out vArray))
            {
                return;
            }

            if (vArray.BsonType != BsonType.Array)
            {
                throw new InvalidOperationException(string.Format(null, @"Value ""{0}"" must be array.", name));
            }

            var array = vArray.AsBsonArray;

            if (!all && value.BsonType == BsonType.Document)
            {
                //_131130_103226 Created in Update.Pull(query)
                var wrapper = value as BsonDocumentWrapper;
                if (wrapper != null)
                {
                    value = (BsonValue)wrapper.WrappedObject;
                }

                var predicate = QueryCompiler.GetFunction(value.AsBsonDocument);
                for (int i = array.Count; --i >= 0;)
                {
                    var v = array[i];
                    if (v.BsonType == BsonType.Document && predicate(v.AsBsonDocument))
                    {
                        array.RemoveAt(i);
                    }
                }
            }
            else
            {
                BsonArray values = all ? value.AsBsonArray : null;
                for (int i = array.Count; --i >= 0;)
                {
                    if (values == null)
                    {
                        if (value.CompareTo(array[i]) == 0)
                        {
                            array.RemoveAt(i);
                        }
                    }
                    else
                    {
                        if (values.ContainsByCompareTo(array[i]))
                        {
                            array.RemoveAt(i);
                        }
                    }
                }
            }
        }
예제 #7
0
 IEnumerable <BsonDocument> QueryDocuments(IMongoQuery query)
 {
     return(Documents.Where(QueryCompiler.GetFunction(query.ToBsonDocument())));
 }
예제 #8
0
        }                                                                                                                                   //! DB text

        // Assume that keys are already unique, so we avoid many checks.
        FieldCompiler(IMongoFields fields)
        {
            var document = ((IConvertibleToBsonDocument)fields).ToBsonDocument();

            if (document.ElementCount == 0)
            {
                _All = true;
                return;
            }

            foreach (var e in document)
            {
                var name  = e.Name;
                var value = e.Value;
                if (value.IsNumeric)
                {
                    if (e.Value.ToInt32() != 0)
                    {
                        // include
                        if (_Exclude != null)
                        {
                            ThrowMix();
                        }

                        if (_Include == null)
                        {
                            _Include = new List <string>();
                        }

                        if (name != MyValue.Id)
                        {
                            _Include.Add(name);
                        }
                    }
                    else
                    {
                        // exclude
                        if (name == MyValue.Id)
                        {
                            _Id = false;
                            continue;
                        }

                        if (_Include != null)
                        {
                            ThrowMix();
                        }

                        if (_Exclude == null)
                        {
                            _Exclude = new List <string>();
                        }

                        _Exclude.Add(name);
                    }
                    continue;
                }

                BsonDocument selector;
                if (value.BsonType != BsonType.Document || (selector = value.AsBsonDocument).ElementCount != 1)
                {
                    throw new InvalidOperationException("Invalid type of fields.");
                }

                var element = selector.GetElement(0);
                var oper    = element.Name;
                var arg     = element.Value;

                // case slice
                if (oper == "$slice")
                {
                    if (arg.IsNumeric)
                    {
                        _Slice.Add(name, new int[] { 0, arg.ToInt32() });
                        continue;
                    }

                    BsonArray array;
                    if (arg.BsonType != BsonType.Array || (array = arg.AsBsonArray).Count != 2)
                    {
                        throw new InvalidOperationException("Invalid $slice argument.");
                    }

                    int n = array[1].ToInt32();
                    if (n <= 0)
                    {
                        throw new InvalidOperationException("$slice limit must be positive.");                         //! DB text
                    }
                    _Slice.Add(name, new int[] { array[0].ToInt32(), n });
                    continue;
                }

                // case match

                if (oper != "$elemMatch")
                {
                    throw new InvalidOperationException("Invalid field operator.");
                }

                if (arg.BsonType != BsonType.Document)
                {
                    throw new InvalidOperationException("Invalid field match argument.");
                }

                _ElemMatch.Add(name, QueryCompiler.GetFunction(arg.AsBsonDocument));
            }
        }
예제 #9
0
 IEnumerable <BsonDocument> QueryDocuments(IMongoQuery query)
 {
     return(Documents.Where(QueryCompiler.GetFunction((IConvertibleToBsonDocument)query)));
 }