博客园新闻招聘找找看知识库

MongoDB数据库C#驱动Distinct的写法

0
悬赏园豆:100 [已解决问题] 浏览: 1235次

我要对查询结果去重复

根据DeviceID去重复

谁知道C#中如何去写?

Small_Truth的主页 Small_Truth | 初学一级 | 园豆:24
提问于:2012-07-18 11:30
最佳答案
2
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
收获园豆:100
水牛刀刀 | 大侠五级 |园豆:6063 | 2012-07-18 11:40

我看代码提示里,这个Distinct方法有两个重载,一个是直接Distinct()就可以了

另一个是带参数的Distinct(IEqualityComparer<BsonDocument> compare)

你上面发的确实可以实现去重复的操作,但是如果直接使用该方法函数加DeviceId参数不可以实现?

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 11:48

@Small_Truth: 我刚误解了你的意思,看我修改的答案。

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 11:52
 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 | 园豆:24 (初学一级) | 2012-07-18 11:59

@Small_Truth: 你调用了.Take(50)这个方法,那么就是LINQ TO OBJECTS里的Take方法了,你之前的mongodb查询就会被执行。最好的做法是全部在数据库里完成。跟.Take方法有同样效果的是.Limit方法。你改成

.SetSortOrder(....).Limit(50).Distinct("DeviceID").ToList();
水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 12:05

@水牛刀刀: 我使用了Limit方法提示错误,“不能以方法的方式使用不可调用的'MongoDB.Driver.MongoCursor.Limit"

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 12:27

@Small_Truth: 打错了,不是Limit(50),是 SetLimit(50)

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 13:24

@水牛刀刀:  “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);

是不是这个我没有声明的问题?

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 13:34
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: 

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 13:49

@水牛刀刀: 

 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”类型的表达式

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 14:05

@水牛刀刀: 因为我方法的返回类型是List<AlarmData>

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 15:16

@Small_Truth: collectionAlarm是什么类型

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 15:45

@水牛刀刀: MongoCollection<BsonDocument>

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 15:57

@Small_Truth: 为什么不是 MongoCollection<AlarmData>啊,你应该用强类型查询啊。

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 16:17

@水牛刀刀: 暂时是这么个情况。

我也很头疼的。返回类型还没法改变

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 16:25

@Small_Truth: 你QQ告诉我,QQ上弄比较快一点。

水牛刀刀 | 园豆:6063 (大侠五级) | 2012-07-18 16:26
其他回答(1)
1
artwl | 园豆:16468 (专家六级) | 2012-07-18 11:42

能帮我看下吗

Small_Truth | 园豆:24 (初学一级) | 2012-07-18 14:21
   您需要登录以后才能回答,未注册用户请先注册