/// <summary> /// Watches changes on all collections in all databases. /// </summary> /// <param name="client">The client.</param> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A change stream. /// </returns> public static IAsyncCursor <ChangeStreamDocument <BsonDocument> > Watch( this IMongoClient client, ChangeStreamOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(client, nameof(client)); var emptyPipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >(); return(client.Watch(emptyPipeline, options, cancellationToken)); }
/// <summary> /// Watches changes on all collection in a database. /// </summary> /// <param name="database">The database.</param> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A change stream. /// </returns> public static Task <IAsyncCursor <ChangeStreamDocument <BsonDocument> > > WatchAsync( this IMongoDatabase database, ChangeStreamOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(database, nameof(database)); var emptyPipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >(); return(database.WatchAsync(emptyPipeline, options, cancellationToken)); }
private static PipelineDefinition <ChangeStreamDocument <Product>, ChangeStreamDocument <Product> > BuildPipelineDefinition() { var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <Product> >() .Match(x => x.FullDocument.PublishStatus == false && (x.OperationType == ChangeStreamOperationType.Insert || x.OperationType == ChangeStreamOperationType.Update)); return(pipeline); }
public void Sample_should_add_expected_stage() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); var result = pipeline.Sample(15); var stages = RenderStages(result, BsonDocumentSerializer.Instance); stages.Count.Should().Be(1); stages[0].Should().Be("{ $sample: { size: 15 } }"); }
protected Task cofigureWatcher <WatchType>( IMongoCollection <WatchType> collectionToMonitor, Func <ChangeStreamDocument <WatchType>, Task> watchFunction, ChangeStreamOperationType operationType, ChangeStreamFullDocumentOption changeStreamDocumentOption = ChangeStreamFullDocumentOption.UpdateLookup, byte secondsToWait = 2) { var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <WatchType> >().Match(x => x.OperationType == operationType); return(buildWatcher(pipeline, changeStreamDocumentOption, secondsToWait, watchFunction, collectionToMonitor)); }
public async Task <bool> WatchCollectionAsync <T>(string collectionName, Expression <Func <ChangeStreamDocument <T>, bool> > filter) { var collection = db.GetCollection <T>(collectionName); var filterDefinition = Builders <ChangeStreamDocument <T> > .Filter.Where(filter); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <T> >().Match(filterDefinition); var changeQueueStream = await collection.WatchAsync(pipeline); return(changeQueueStream.ToEnumerable().GetEnumerator().MoveNext()); }
public void ChangestreamExample4() { RequireServer.Check().Supports(Feature.AggregateAddFields); var client = DriverTestConfiguration.Client; var database = client.GetDatabase("ChangeStreamExamples"); database.DropCollection("inventory"); var cancelationTokenSource = new CancellationTokenSource(); try { var document = new BsonDocument("username", "alice"); Task.Run(() => { var inventoryCollection = database.GetCollection <BsonDocument>("inventory"); while (!cancelationTokenSource.IsCancellationRequested) { Thread.Sleep(TimeSpan.FromMilliseconds(100)); document["_id"] = ObjectId.GenerateNewId(); inventoryCollection.InsertOne(document); } }, cancelationTokenSource.Token); // Start Changestream Example 4 var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >() .Match(change => change.FullDocument["username"] == "alice" || change.OperationType == ChangeStreamOperationType.Delete) .AppendStage <ChangeStreamDocument <BsonDocument>, ChangeStreamDocument <BsonDocument>, BsonDocument>( "{ $addFields : { newField : 'this is an added field!' } }"); var collection = database.GetCollection <BsonDocument>("inventory"); using (var changeStream = collection.Watch(pipeline)) { using (var enumerator = changeStream.ToEnumerable().GetEnumerator()) { if (enumerator.MoveNext()) { var next = enumerator.Current; } } } // End Changestream Example 4 } finally { cancelationTokenSource.Cancel(); } }
private static async Task TriggerChangeStreamAsync() { Console.WriteLine("TriggerChangeStream Method start"); try { MongoClient dbClient = new MongoClient("mongodb://*****:*****@deliverymoment-cosmos-mongo-db.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&maxIdleTimeMS=120000&appName=@deliverymoment-cosmos-mongo-db@"); //Database List //Get Database and Collection Console.WriteLine("Get Database : deliverymoment-db :"); IMongoDatabase db = dbClient.GetDatabase("deliverymoment-db"); Console.WriteLine("Get Deilverymoment Collection :"); var deliveryColl = db.GetCollection <BsonDocument>("delivery-moment"); Console.WriteLine("Changestream code start"); //change feed code start var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >() .Match(change => change.OperationType == ChangeStreamOperationType.Insert || change.OperationType == ChangeStreamOperationType.Update || change.OperationType == ChangeStreamOperationType.Replace) .AppendStage <ChangeStreamDocument <BsonDocument>, ChangeStreamDocument <BsonDocument>, BsonDocument>( "{ $project: { '_id': 1, 'fullDocument': 1, 'ns': 1, 'documentKey': 1 }}"); var options = new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup }; var enumerator = deliveryColl.Watch(pipeline, options).ToEnumerable().GetEnumerator(); Console.WriteLine("Reading Change stream while loop start"); while (enumerator.MoveNext()) { //publish message to Confluent Kafka var document = enumerator.Current; Console.WriteLine($"Start publishing messaage : {document}"); await DeliveryMomentMessageHandler.PublishMessage(document.ToString()); Console.WriteLine($"End publishing messaage : {document}"); } enumerator.Dispose(); Console.WriteLine("Reading Change stream while loop end"); //change feed code end } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); } Console.WriteLine("TriggerChangeStream Method end"); }
public void UnionWith_should_throw_when_withCollection_is_null() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); IMongoCollection <BsonDocument> withCollection = null; var withPipeline = new EmptyPipelineDefinition <BsonDocument>(); var exception = Record.Exception(() => pipeline.UnionWith(withCollection, withPipeline)); var argumentNullException = exception.Should().BeOfType <ArgumentNullException>().Subject; argumentNullException.ParamName.Should().Be("withCollection"); }
public void ChangeStream_should_add_the_expected_stage_when_options_is_null() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); ChangeStreamStageOptions options = null; var result = pipeline.ChangeStream(options); var stages = RenderStages(result); stages.Count.Should().Be(1); stages[0].Should().Be("{ $changeStream : { fullDocument : \"default\" } }"); }
/// <summary> /// Watches changes on all collection in a database. /// </summary> /// <param name="database">The database.</param> /// <param name="session">The session.</param> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A change stream. /// </returns> public static IChangeStreamCursor <ChangeStreamDocument <BsonDocument> > Watch( this IMongoDatabase database, IClientSessionHandle session, ChangeStreamOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(database, nameof(database)); Ensure.IsNotNull(session, nameof(session)); var emptyPipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >(); return(database.Watch(session, emptyPipeline, options, cancellationToken)); }
/// <summary> /// Watches changes on all collections in all databases. /// </summary> /// <param name="client">The client.</param> /// <param name="session">The session.</param> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A change stream. /// </returns> public static Task <IChangeStreamCursor <ChangeStreamDocument <BsonDocument> > > WatchAsync( this IMongoClient client, IClientSessionHandle session, ChangeStreamOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(client, nameof(client)); Ensure.IsNotNull(session, nameof(session)); var emptyPipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >(); return(client.WatchAsync(session, emptyPipeline, options, cancellationToken)); }
//-----------------------------------------------------// #region Watch One Collection for any kind of a change public bool WatchDatabase() { var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >().Match(x => x.OperationType == ChangeStreamOperationType.Delete || x.OperationType == ChangeStreamOperationType.Insert || x.OperationType == ChangeStreamOperationType.Update || x.OperationType == ChangeStreamOperationType.Replace ); var change = db.Watch(pipeline).ToEnumerable().GetEnumerator(); return(change.MoveNext()); }
public IChangeStreamCursor <ChangeStreamDocument <Notification> > Watch(string userId, CancellationToken cancellationToken) { var filter = Builders <ChangeStreamDocument <Notification> > .Filter.And( Builders <ChangeStreamDocument <Notification> > .Filter.Eq(n => n.OperationType, ChangeStreamOperationType.Insert), Builders <ChangeStreamDocument <Notification> > .Filter.Eq(n => n.FullDocument.UserLogin, userId) ); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <Notification> >() .Match(filter); return(Collection.Watch(pipeline, new ChangeStreamOptions { }, cancellationToken)); }
public async Task <IChangeStreamCursor <ChangeStreamDocument <Notification> > > GetNotificationChangeStreamCursorAsync() { var mongoClient = new MongoClient(_server); IMongoDatabase database = mongoClient.GetDatabase(_database); var collection = database.GetCollection <Notification>(_collection); var options = new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup }; var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <Notification> >().Match("{ operationType: { $in: [ 'insert' ] } }"); IChangeStreamCursor <ChangeStreamDocument <Notification> > cursor = await collection.WatchAsync(pipeline, options); return(cursor); }
public void UnionWith_should_throw_when_TWith_is_not_the_same_with_TInput_and_withPipeline_is_null() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); var withCollection = Mock.Of <IMongoCollection <object> >( coll => coll.CollectionNamespace == CollectionNamespace.FromFullName("db.test")); var exception = Record.Exception(() => pipeline.UnionWith(withCollection, withPipeline: null)); var e = exception.Should().BeOfType <ArgumentException>().Subject; e.Message.Should().StartWith("The withPipeline cannot be null when TWith != TInput. A pipeline is required to transform the TWith documents to TInput documents."); e.ParamName.Should().Be("withPipeline"); }
public void Aggregate_with_write_stage_should_not_have_transaction_id( [Values("$out", "$merge")] string outStage, [Values(false, true)] bool async) { RequireServer .Check() .ClusterTypes(ClusterType.ReplicaSet, ClusterType.Sharded) .Serverless(false); // $out and $merge are not supported on serverless. if (outStage == "$merge") { RequireServer.Check().Supports(Feature.AggregateMerge); } DropAndCreateCollection(); var eventCapturer = CreateEventCapturer(); using (var client = CreateDisposableClient(eventCapturer)) { var database = client.GetDatabase(_databaseName); var collection = database.GetCollection <BsonDocument>(_collectionName); PipelineDefinition <BsonDocument, BsonDocument> pipeline = new EmptyPipelineDefinition <BsonDocument>(); var outputCollection = database.GetCollection <BsonDocument>(_collectionName + "-outputCollection"); switch (outStage) { case "$out": pipeline = pipeline.Out(outputCollection); break; case "$merge": var mergeOptions = new MergeStageOptions <BsonDocument>(); pipeline = pipeline.Merge(outputCollection, mergeOptions); break; default: throw new Exception($"Unexpected outStage: {outStage}."); } if (async) { collection.AggregateAsync(pipeline).GetAwaiter().GetResult(); } else { collection.Aggregate(pipeline); } AssertCommandDoesNotHaveTransactionId(eventCapturer); } }
public void UnionWith_should_add_expected_stage() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); var withCollection = Mock.Of <IMongoCollection <BsonDocument> >( coll => coll.CollectionNamespace == CollectionNamespace.FromFullName("db.test")); var withPipeline = new EmptyPipelineDefinition <BsonDocument>() .AppendStage <BsonDocument, BsonDocument, BsonDocument>("{ $match : { b : 1 } }"); var result = pipeline.UnionWith(withCollection, withPipeline); var stages = RenderStages(result, BsonDocumentSerializer.Instance); stages[0].Should().Be("{ $unionWith : { coll : 'test', pipeline : [{ $match : { b : 1 } }] } }"); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var options = new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup }; var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <User> >() .Match(x => x.OperationType == ChangeStreamOperationType.Replace || x.OperationType == ChangeStreamOperationType.Update); using var cursor = _users.Watch(pipeline, options, stoppingToken); await cursor.ForEachAsync(async document => { await _userHubContext.SendUpdateAsync(document.FullDocument); }, stoppingToken); }
public bool WatchCollection <T>(string collectionName, Expression <Func <ChangeStreamDocument <T>, bool> > filter, out int changeCount) { var collection = db.GetCollection <T>(collectionName); var filterDefinition = Builders <ChangeStreamDocument <T> > .Filter.Where(filter); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <T> >().Match(filterDefinition); var changeCursor = collection.Watch(pipeline); changeCount = changeCursor.Current.Count(); var changeCursorEnumerator = changeCursor.ToEnumerable().GetEnumerator(); return(changeCursorEnumerator.MoveNext()); }
public void Merge_should_add_expected_stage() { var pipeline = new EmptyPipelineDefinition <BsonDocument>(); var client = DriverTestConfiguration.Client; var outputDatabase = client.GetDatabase("database"); var outputCollection = outputDatabase.GetCollection <BsonDocument>("collection"); var mergeOptions = new MergeStageOptions <BsonDocument>(); var result = pipeline.Merge(outputCollection, mergeOptions); var stages = RenderStages(result, BsonDocumentSerializer.Instance); stages.Count.Should().Be(1); stages[0].Should().Be("{ $merge : { into : { db : 'database', coll : 'collection' } } }"); }
public async Task <bool> WatchDatabaseAsync() { var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >().Match(x => x.OperationType == ChangeStreamOperationType.Delete || x.OperationType == ChangeStreamOperationType.Insert || x.OperationType == ChangeStreamOperationType.Update || x.OperationType == ChangeStreamOperationType.Replace ); var change = await db.WatchAsync(pipeline); var enumerator = change.ToEnumerable().GetEnumerator(); return(enumerator.MoveNext()); }
protected void ChangeStreamsSync(ChangeStreamOperationType changeStreamOperationType, Action <TEntity> action) { var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <TEntity> >().Match(x => x.OperationType == changeStreamOperationType); using (var cursor = Collection <TEntity>().Watch(pipeline)) { cursor.ForEachAsync(change => { if (change.OperationType == changeStreamOperationType) { action(change.FullDocument); } }); } }
public static void WatchForChanges() { var pipeline = new EmptyPipelineDefinition <Geodata>().Match("{ operationType: { $eq: 'update' } }"); var client = new MongoClient("mongodb+srv://Fetcher:[email protected]/test?retryWrites=true&w=majority"); var database = client.GetDatabase("GEM"); collection = database.GetCollection <Geodata>("Geodata"); using (var cursor = collection.Watch()) { foreach (var change in cursor.ToEnumerable()) { UpdateSurvey(); } } }
public async Task <bool> WatchCollectionAsync <T>(string collectionName) { var collection = db.GetCollection <T>(collectionName); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <T> >().Match(x => x.OperationType == ChangeStreamOperationType.Delete || x.OperationType == ChangeStreamOperationType.Insert || x.OperationType == ChangeStreamOperationType.Update || x.OperationType == ChangeStreamOperationType.Replace ); var changeQueueStream = await collection.WatchAsync(sessionHandle, pipeline); var enumerator = changeQueueStream.ToEnumerable().GetEnumerator(); return(enumerator.MoveNext()); }
private static PipelineDefinition <ChangeStreamDocument <MongoEventCommit>, ChangeStreamDocument <MongoEventCommit> >?Match(string?streamFilter) { var result = new EmptyPipelineDefinition <ChangeStreamDocument <MongoEventCommit> >(); var byStream = Filtering.ByChangeInStream(streamFilter); if (byStream != null) { var filterBuilder = Builders <ChangeStreamDocument <MongoEventCommit> > .Filter; var filter = filterBuilder.Or(filterBuilder.Ne(x => x.OperationType, ChangeStreamOperationType.Insert), byStream); return(result.Match(filter)); } return(result); }
public bool WatchCollection <T>(string collectionName) { var collection = db.GetCollection <T>(collectionName); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <T> >().Match(x => x.OperationType == ChangeStreamOperationType.Delete || x.OperationType == ChangeStreamOperationType.Insert || x.OperationType == ChangeStreamOperationType.Update || x.OperationType == ChangeStreamOperationType.Replace ); var changeCursor = collection.Watch(sessionHandle, pipeline); var changeCursorEnumerator = changeCursor.ToEnumerable().GetEnumerator(); return(changeCursorEnumerator.MoveNext()); }
protected override async Task ExecuteAsync(CancellationToken cancellationToken) { var client = new MongoClient(_mongoOptions.ConnectionString); var database = client.GetDatabase(_mongoOptions.Database); var collection = database.GetCollection <BlogPost>(nameof(BlogPost)); var insertOperationsOnlyFilter = new EmptyPipelineDefinition <ChangeStreamDocument <BlogPost> >().Match(x => x.OperationType == ChangeStreamOperationType.Insert); var blogPostFeed = new MongoDbChangeStreamFeed <BlogPost>(collection, TimeSpan.FromSeconds(5)); try { await foreach (var blog in blogPostFeed.FetchFeed(insertOperationsOnlyFilter, cancellationToken)) { await _blogHub.Clients.All.BlogPostCreated(blog); } } catch (OperationCanceledException) { } }
public void CreateChangeStreamOperation_for_collection_returns_expected_result() { var databaseNamespace = new DatabaseNamespace("databaseName"); var collectionNamespace = new CollectionNamespace(databaseNamespace, "collectionName"); var mockCollection = new Mock <IMongoCollection <BsonDocument> >(); mockCollection.SetupGet(m => m.CollectionNamespace).Returns(collectionNamespace); var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >().Limit(1); var documentSerializer = BsonDocumentSerializer.Instance; var options = new ChangeStreamOptions { BatchSize = 123, Collation = new Collation("en-us"), FullDocument = ChangeStreamFullDocumentOption.UpdateLookup, FullDocumentBeforeChange = ChangeStreamFullDocumentBeforeChangeOption.Off, MaxAwaitTime = TimeSpan.FromSeconds(123), ResumeAfter = new BsonDocument(), StartAfter = new BsonDocument(), StartAtOperationTime = new BsonTimestamp(1, 2) }; var readConcern = new ReadConcern(); var messageEncoderSettings = new MessageEncoderSettings(); var renderedPipeline = RenderPipeline(pipeline); var result = ChangeStreamHelper.CreateChangeStreamOperation(mockCollection.Object, pipeline, documentSerializer, options, readConcern, messageEncoderSettings, true); result.BatchSize.Should().Be(options.BatchSize); result.Collation.Should().BeSameAs(options.Collation); result.CollectionNamespace.Should().BeSameAs(collectionNamespace); result.DatabaseNamespace.Should().BeNull(); result.FullDocument.Should().Be(options.FullDocument); result.FullDocumentBeforeChange.Should().Be(options.FullDocumentBeforeChange); result.MaxAwaitTime.Should().Be(options.MaxAwaitTime); result.MessageEncoderSettings.Should().BeSameAs(messageEncoderSettings); result.Pipeline.Should().Equal(renderedPipeline.Documents); result.ReadConcern.Should().BeSameAs(readConcern); result.ResultSerializer.Should().BeOfType <ChangeStreamDocumentSerializer <BsonDocument> >(); result.ResumeAfter.Should().BeSameAs(options.ResumeAfter); result.RetryRequested.Should().Be(true); result.StartAfter.Should().BeSameAs(options.StartAfter); result.StartAtOperationTime.Should().BeSameAs(options.StartAtOperationTime); }
public static IObservable <ChangeStreamDocument <T> > WhenCollectionChanges <T>(this IMongoCollection <T> collection, CancellationToken cancellationToken = default, params ChangeStreamOperationType[] operationTypes) { if (operationTypes.Length == 0) { operationTypes = new[] { ChangeStreamOperationType.Insert, ChangeStreamOperationType.Update, ChangeStreamOperationType.Replace, ChangeStreamOperationType.Delete }; } // { operationType: { $in: [...] } } var filter = new FilterDefinitionBuilder <ChangeStreamDocument <T> >() .In(d => d.OperationType, operationTypes); var pipelineDefinition = new EmptyPipelineDefinition <ChangeStreamDocument <T> >() .Match(filter); var options = new ChangeStreamOptions() { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup }; var changeStreamCursor = collection.Watch(pipelineDefinition, options, cancellationToken); return(Observable.Create <ChangeStreamDocument <T> >(observer => { Task.Run(async() => { while (true) { if (await changeStreamCursor.MoveNextAsync(cancellationToken)) { foreach (var c in changeStreamCursor.Current) { observer.OnNext(c); cancellationToken.ThrowIfCancellationRequested(); } } cancellationToken.ThrowIfCancellationRequested(); } }, cancellationToken); return Disposable.Create(() => changeStreamCursor.Dispose()); })); }