MongoCollection collection =... //这是你的 collection collection.FindAllAs<Device>().Distinct() //在你的查询最后加个Distinct方法就可以了,前提是: //你的Device类重载Equals和GetHashCode class Device { public bool Equals(object o) { var d = o as Device; return d != null && d.DeviceID == this.DeviceID; } public int GetHashCode() { return this.DeviceID * 23 + 7; } }
通过重载Equals和GetHashCode,具有相同DeviceID的Device实例被看做是相等的。
EDIT sorry我刚可能误解了,LZ可能是希望通过mongodb的C# driver在数据库层面进行distinct,而不是像我上面答案上那样查询到内存中通过LINQ TO OBJECTS进行distinct。数据库层面的distinct看driver里的这两个重载:
public virtual IEnumerable<BsonValue> Distinct(string key); public virtual IEnumerable<BsonValue> Distinct(string key, IMongoQuery query);
collection.Distinct("age", Query.EQ("name", "test"));
//name为test的查询结果根据age进行Distinct
我看代码提示里,这个Distinct方法有两个重载,一个是直接Distinct()就可以了
另一个是带参数的Distinct(IEqualityComparer<BsonDocument> compare)
你上面发的确实可以实现去重复的操作,但是如果直接使用该方法函数加DeviceId参数不可以实现?
@Small_Truth: 我刚误解了你的意思,看我修改的答案。
var result = this.collectionAlarm.Find(Query.And( Query.GTE("Time", BsonDateTime.Create(start)), Query.LTE("Time", BsonDateTime.Create(end)), Query.GTE("Latitude", BsonDouble.Create(l_corr[1])), Query.LTE("Latitude", BsonDouble.Create(r_corr[1])), Query.GTE("Longitude", BsonDouble.Create(l_corr[0])), Query.LTE("Longitude", BsonDouble.Create(r_corr[0])) )).SetSortOrder(SortBy.Descending("Time")).Take(50).Distinct().ToList();
这是我的查询,按照您刚才所说。
我是不是可以直接Distinct(“DeviceId”).ToList();我这么写了报错
我初学者,能稍微详细点吗,谢谢了
@Small_Truth: 你调用了.Take(50)这个方法,那么就是LINQ TO OBJECTS里的Take方法了,你之前的mongodb查询就会被执行。最好的做法是全部在数据库里完成。跟.Take方法有同样效果的是.Limit方法。你改成
.SetSortOrder(....).Limit(50).Distinct("DeviceID").ToList();
@水牛刀刀: 我使用了Limit方法提示错误,“不能以方法的方式使用不可调用的'MongoDB.Driver.MongoCursor.Limit"
@Small_Truth: 打错了,不是Limit(50),是 SetLimit(50)
@水牛刀刀: “MongoDB.Driver.MongoCursor<MongoDB.Bson.BsonDocument>”不包含“Distinct”的定义,并且最佳扩展方法重载“System.Linq.Enumerable.Distinct<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Collections.Generic.IEqualityComparer<TSource>)”的某些参数无效
这个什么情况,
public virtual IEnumerable<BsonValue> Distinct(string key);
public virtual IEnumerable<BsonValue> Distinct(string key, IMongoQuery query);
是不是这个我没有声明的问题?
var result = this.collectionAlarm.Distinct("DeviceID", this.collectionAlarm.Find(Query.And( Query.GTE("Time", BsonDateTime.Create(1)), Query.LTE("Time", BsonDateTime.Create(2)), Query.GTE("Latitude", BsonDouble.Create(3)), Query.LTE("Latitude", BsonDouble.Create(4)), Query.GTE("Longitude", BsonDouble.Create(5)), Query.LTE("Longitude", BsonDouble.Create(6)))) .SetSortOrder(SortBy.Descending("Time")) .SetLimit(50).Query) .ToList();
把我代码里的1 2 3 4 5 6换成你自己的参数试试。我这里没法测试,只能手动给你写。
@Small_Truth:
@水牛刀刀:
var list = result.ConvertAll(d => new AlarmData() { DeviceId = d["DeviceId"].AsString, Direction = d["Direction"].AsDouble, Address = d["Address"].AsString, Latitude = d["Latitude"].AsDouble, Longitude = d["Longitude"].AsDouble, DeviceName = d["DeviceName"].AsString, CompanyName = d["CompanyName"].AsString, EncryptPosition = d["EncryptPosition"].AsString, UId = d["UID"].AsString, Speed = d["Speed"].AsDouble, Time = d["Time"].AsDateTime.ToLocalTime(), Category = (AlarmCategory)Enum.Parse(typeof(AlarmCategory), d["Category"].AsInt32.ToString()), Type = (AlarmDataType)Enum.Parse(typeof(AlarmDataType), d["Type"].AsInt32.ToString()), IsLocked = d["IsLocked"].AsBoolean });
上面语法不 报错了,但是我下面的逻辑出问题了,都是一样的问题
无法将带 [] 的索引应用于“MongoDB.Bson.BsonValue”类型的表达式
@水牛刀刀: 因为我方法的返回类型是List<AlarmData>
@Small_Truth: collectionAlarm是什么类型
@水牛刀刀: MongoCollection<BsonDocument>
@Small_Truth: 为什么不是 MongoCollection<AlarmData>啊,你应该用强类型查询啊。
@水牛刀刀: 暂时是这么个情况。
我也很头疼的。返回类型还没法改变
@Small_Truth: 你QQ告诉我,QQ上弄比较快一点。