예제 #1
0
        /// <summary>
        /// Update documents using transform expression (must return a scalar/document value) using predicate as filter
        /// </summary>
        public int UpdateMany(string collection, BsonExpression transform, BsonExpression predicate)
        {
            if (collection.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(collection));
            }
            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            return(this.Update(collection, transformDocs()));

            IEnumerable <BsonDocument> transformDocs()
            {
                var q = new Query {
                    Select = "$", ForUpdate = true
                };

                if (predicate != null)
                {
                    q.Where.Add(predicate);
                }

                using (var reader = this.Query(collection, q))
                {
                    while (reader.Read())
                    {
                        var doc = reader.Current.AsDocument;

                        var id    = doc["_id"];
                        var value = transform.ExecuteScalar(doc, _header.Pragmas.Collation);

                        if (!value.IsDocument)
                        {
                            throw new ArgumentException("Extend expression must return a document", nameof(transform));
                        }

                        var result = BsonExpressionMethods.EXTEND(doc, value.AsDocument).AsDocument;

                        // be sure result document will contain same _id as current doc
                        if (result.TryGetValue("_id", out var newId))
                        {
                            if (newId != id)
                            {
                                throw LiteException.InvalidUpdateField("_id");
                            }
                        }
                        else
                        {
                            result["_id"] = id;
                        }

                        yield return(result);
                    }
                }
            }
        }