public async Task <MessageResult> GetMessageAsyncLite( GetMessageRequest request, Delegate_outputMessage proc, TimeSpan timeout, CancellationToken token) { MessageResult result = new MessageResult(); if (string.IsNullOrEmpty(request.TaskID) == true) { request.TaskID = Guid.NewGuid().ToString(); } long recieved = 0; StringBuilder cache = new StringBuilder(); using (WaitEvents wait_events = new WaitEvents()) // 表示中途数据到来 { using (var handler = HubProxy.On < string, long, long, IList <MessageRecord>, string, string>( "responseGetMessage", (taskID, resultCount, start, records, errorInfo, errorCode) => { if (taskID != request.TaskID) { return; } if (resultCount == -1 || start == -1) { if (start == -1) { // 表示发送响应过程已经结束。只是起到通知的作用,不携带任何信息 // result.Finished = true; } else { result.Value = resultCount; result.ErrorInfo = errorInfo; result.String = errorCode; } wait_events.finish_event.Set(); return; } proc( cache, resultCount, start, records, errorInfo, errorCode); if (records != null) { recieved += GetCount(records); // records.Count; } if (errorCode == "_complete") { result.Value = resultCount; wait_events.finish_event.Set(); return; } if (resultCount >= 0 && IsComplete(request.Start, request.Count, resultCount, recieved) == true) { wait_events.finish_event.Set(); } else { wait_events.active_event.Set(); } })) { MessageResult temp = await HubProxy.Invoke <MessageResult>( "RequestGetMessage", request).ConfigureAwait(false); if (temp.Value == -1 || temp.Value == 0 || temp.Value == 2) { return(temp); } // result.String 里面是返回的 taskID await WaitAsync( request.TaskID, wait_events, timeout, token).ConfigureAwait(false); return(result); } } }
// parameters: // field 字段名。例如 groups/subjects public async Task GetFieldAggregate( string field, GroupQuery group_query, string userCondition, string timeRange, string idCondition, string subjectCondition, int start, int count, Delegate_outputMessage proc) { IMongoCollection <MessageItem> collection = this._collection; FilterDefinition <MessageItem> filter = BuildQuery(// groupName, group_query, userCondition, timeRange, idCondition, subjectCondition); #if NO var group = new BsonDocument { { "$group", new BsonDocument { { "_id", new BsonDocument { { "MyUser", "$subject" } } }, { "Count", new BsonDocument { { "$sum", 1 } } } } } }; #endif var myresults = await collection.Aggregate().Match(filter) //.Group(new BsonDocument("_id", "$subjects")) .Group( new BsonDocument { { "_id", "$" + field }, { "c", new BsonDocument { { "$sum", 1 } } } } ) .ToListAsync().ConfigureAwait(false); long totalCount = myresults.Count; var index = 0; foreach (BsonDocument doc in myresults) { if (count != -1 && index - start >= count) { break; } Type type = null; if (index >= start) { MessageItem item = new MessageItem(); // BsonArray array = (doc.GetValue("_id") as BsonArray); if (type == null) { type = item.GetPropertyType(field); } BsonValue temp = doc.GetValue("_id"); if (type.Equals(typeof(string[]))) { item.SetPropertyValue(field, GetStringArray(temp as BsonArray)); } else if (type.Equals(typeof(List <string>))) // 2018/11/14 { item.SetPropertyValue(field, new List <string>(GetStringArray(temp as BsonArray))); } else { item.SetPropertyValue(field, temp.ToString()); } item.data = doc.GetValue("c").ToString(); if (proc(totalCount, item) == false) { return; } } index++; } proc(totalCount, null); // 表示结束 }
// 检索出指定范围的 群名类型 public async Task GetGroups( GroupQuery group_query, string timeRange, int start, int count, Delegate_outputMessage proc) { IMongoCollection <MessageItem> collection = this._collection; // List<MessageItem> results = new List<MessageItem>(); FilterDefinition <MessageItem> filter = BuildQuery(// groupName, group_query, timeRange); var results = await collection .Find( filter == null?new BsonDocument() : filter ) .Project(Builders <MessageItem> .Projection.Include("groups")).ToListAsync(); List <string> keys = new List <string>(); Hashtable table = new Hashtable(); // groups --> true foreach (BsonDocument doc in results) { string strText = ToString(doc.GetValue("groups") as BsonArray); if (strText == null) { continue; } if (table.ContainsKey(strText)) { continue; } table[strText] = true; keys.Add(strText); } long totalCount = keys.Count; foreach (string key in keys) { MessageItem item = new MessageItem(); item.groups = key.Split(new char [] { ',' }); // var groups = doc.GetValue("_id"); if (proc(totalCount, item) == false) { return; } } proc(totalCount, null); // 表示结束 #if NO var myresults = await collection.Aggregate() .Group(new BsonDocument("_id", "$groups")) .ToListAsync(); long totalCount = myresults.Count; foreach (BsonDocument doc in myresults) { MessageItem item = new MessageItem(); BsonArray array = (doc.GetValue("_id") as BsonArray); item.groups = GetStringArray(array); // var groups = doc.GetValue("_id"); if (proc(totalCount, item) == false) { return; } } proc(totalCount, null); // 表示结束 #endif }
// 这个版本资源耗费厉害 // 按照条件检索出 MessageItem 中的 group 字段,并归并去重 // 相当于 Group by 的效果 public async Task GetGroupsField( GroupQuery group_query, string timeRange, int start, int count, Delegate_outputMessage proc) { IMongoCollection <MessageItem> collection = this._collection; // List<MessageItem> results = new List<MessageItem>(); FilterDefinition <MessageItem> filter = BuildQuery(// groupName, group_query, "", timeRange, "", ""); // 在遍历过程中,只接收 groups 字段 // http://stackoverflow.com/questions/32938656/c-sharp-mongo-2-0-reduce-traffic-of-findasync var projection = Builders <MessageItem> .Projection .Include(b => b.groups) .Exclude("_id"); // _id is special and needs to be explicitly excluded if not needed var options = new FindOptions <MessageItem, MessageItem> { Projection = projection }; List <string> keys = new List <string>(); Hashtable table = new Hashtable(); // groups --> true using (var cursor = await collection.FindAsync(filter, options).ConfigureAwait(false)) { while (await cursor.MoveNextAsync().ConfigureAwait(false)) { var batch = cursor.Current; foreach (var document in batch) { if (document.groups == null) { continue; } string strText = string.Join(",", document.groups); if (table.ContainsKey(strText)) { continue; } table[strText] = true; keys.Add(strText); } } } long totalCount = keys.Count; var index = 0; foreach (string key in keys) { if (count != -1 && index - start >= count) { break; } if (index >= start) { MessageItem item = new MessageItem(); #if ARRAY item.groups = key.Split(new char[] { ',' }); #else item.groups = new List <string>(key.Split(new char[] { ',' })); #endif if (proc(totalCount, item) == false) { return; } } index++; } proc(totalCount, null); // 表示结束 }
// parameters: // timeRange 时间范围 public async Task GetMessages(// string groupName, GroupQuery group_query, string userCondition, string timeRange, string sortCondition, string idCondition, string subjectCondition, int start, int count, Delegate_outputMessage proc) { IMongoCollection <MessageItem> collection = this._collection; // List<MessageItem> results = new List<MessageItem>(); FilterDefinition <MessageItem> filter = BuildQuery(// groupName, group_query, userCondition, timeRange, idCondition, subjectCondition); #if NO if (string.IsNullOrEmpty(groupName)) { filter = Builders <MessageItem> .Filter.Or( Builders <MessageItem> .Filter.Eq("group", ""), Builders <MessageItem> .Filter.Eq("group", (string)null)); } else #endif // filter = Builders<MessageItem>.Filter.Eq("group", groupName); SortDefinition <MessageItem> sort = null; if (string.IsNullOrEmpty(sortCondition)) { sort = Builders <MessageItem> .Sort.Ascending("publishTime"); } else { List <string> sort_params = StringUtil.ParseTwoPart(sortCondition, "|"); string field_name = sort_params[0]; // TODO: 需要检查一下 field_name 内容的正确性 string order_part = sort_params[1]; if (string.IsNullOrEmpty(order_part) || order_part == "ascending" || order_part == "asc") { sort = Builders <MessageItem> .Sort.Ascending(field_name); } else { sort = Builders <MessageItem> .Sort.Descending(field_name); } } var options = new FindOptions <MessageItem, MessageItem> { Sort = sort }; long totalCount = 0; var index = 0; using (var cursor = await collection.FindAsync( filter == null ? new BsonDocument() : filter , options).ConfigureAwait(false)) { while (await cursor.MoveNextAsync().ConfigureAwait(false)) { var batch = cursor.Current; int batch_count = batch.Count <MessageItem>(); Console.WriteLine("batch.Count=" + totalCount); foreach (var document in batch) { if (count != -1 && index - start >= count) { break; } if (index >= start) { if (proc(-2, document) == false) // -2 表示总记录数暂时未知。发送全部结束的时候会单独一次发出总记录数 { return; } } index++; } totalCount += batch_count; } proc(totalCount, null); // 表示结束 } }