// 检索出指定范围的 群名类型 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 myresults = await collection.Aggregate() .Group(new BsonDocument("_id", "$groups")) .ToListAsync(); #if NO BsonArray array = new BsonArray(); array.ToArray <string>(); #endif 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); // 表示结束 }
// 返回空表示任意匹配 // parameters: // userCondiction 消息创建者的用户ID的列表,逗号分隔。如果为空,表示不在意消息创建者 FilterDefinition <MessageItem> BuildQuery(GroupQuery group_query, string userCondition, string timeRange, string idCondition, string subjectCondition) { string strStart = ""; string strEnd = ""; StringUtil.ParseTwoPart(timeRange, "~", out strStart, out strEnd); DateTime startTime; DateTime endTime; try { startTime = string.IsNullOrEmpty(strStart) ? new DateTime(0) : DateTime.Parse(strStart); endTime = string.IsNullOrEmpty(strEnd) ? new DateTime(0) : DateTime.Parse(strEnd); } catch (Exception) { throw new ArgumentException("时间范围字符串 '" + timeRange + "' 不合法", "timeRange"); } FilterDefinition <MessageItem> user_filter = null; if (string.IsNullOrEmpty(userCondition) == false) { string[] list = userCondition.Split(new char[] { ',' }); List <FilterDefinition <MessageItem> > items = new List <FilterDefinition <MessageItem> >(); foreach (string user in list) { string name = user; if (name.StartsWith("ui:")) { name = name.Substring(3); } FilterDefinition <MessageItem> item = Builders <MessageItem> .Filter.Eq("creator", name); items.Add(item); } if (items.Count == 1) { user_filter = items[0]; } else { user_filter = Builders <MessageItem> .Filter.Or(items); } } FilterDefinition <MessageItem> time_filter = null; if (startTime == new DateTime(0) && endTime == new DateTime(0)) { time_filter = null; // Builders<MessageItem>.Filter.Gte("publishTime", startTime); } else if (startTime == new DateTime(0)) { time_filter = Builders <MessageItem> .Filter.Lt("publishTime", endTime); } else if (endTime == new DateTime(0)) { time_filter = Builders <MessageItem> .Filter.Gte("publishTime", startTime); } else { time_filter = Builders <MessageItem> .Filter.And( Builders <MessageItem> .Filter.Gte("publishTime", startTime), Builders <MessageItem> .Filter.Lt("publishTime", endTime)); } FilterDefinition <MessageItem> expire_filter = Builders <MessageItem> .Filter.Or( Builders <MessageItem> .Filter.Eq("expireTime", new DateTime(0)), Builders <MessageItem> .Filter.Gt("expireTime", DateTime.Now)); // 构造一个 AND 运算的检索式 FilterDefinition <MessageItem> group_filter = group_query.BuildMongoQuery(); // id 列表 FilterDefinition <MessageItem> id_filter = null; if (string.IsNullOrEmpty(idCondition) == false) { string[] list = idCondition.Split(new char[] { ',' }); List <FilterDefinition <MessageItem> > items = new List <FilterDefinition <MessageItem> >(); foreach (string id in list) { FilterDefinition <MessageItem> item = Builders <MessageItem> .Filter.Eq("id", id); items.Add(item); } if (items.Count == 1) { id_filter = items[0]; } else { id_filter = Builders <MessageItem> .Filter.Or(items); } } { List <FilterDefinition <MessageItem> > items = new List <FilterDefinition <MessageItem> >(); if (time_filter != null) { items.Add(time_filter); } if (expire_filter != null) { items.Add(expire_filter); } if (group_filter != null) { items.Add(group_filter); } if (user_filter != null) { items.Add(user_filter); } if (id_filter != null) { items.Add(id_filter); } if (string.IsNullOrEmpty(subjectCondition) == false) { items.Add(CollectionQuery.BuildMongoQuery(subjectCondition, "subjects")); } return(Builders <MessageItem> .Filter.And(items)); } #if NO if (time_filter == null) { return(Builders <MessageItem> .Filter.And(expire_filter, group_filter)); } return(time_filter = Builders <MessageItem> .Filter.And(time_filter, expire_filter, group_filter)); #endif }
// 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(); 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 { item.SetPropertyValue(field, temp.ToString()); } item.data = doc.GetValue("c").ToString(); if (proc(totalCount, item) == false) { return; } } index++; } proc(totalCount, null); // 表示结束 }
// 这个版本资源耗费厉害 // 按照条件检索出 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)) { while (await cursor.MoveNextAsync()) { 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(); item.groups = key.Split(new char[] { ',' }); 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 }
// 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)) { while (await cursor.MoveNextAsync()) { 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); // 表示结束 } }
public static GroupQuery Build(string strText) { GroupQuery query = new GroupQuery(strText); return(query); }