MongoDB随机导致C#LINQ

时间:2017-10-07 04:06:18

标签: c# mongodb linq

我正在使用MongoDB的linq驱动程序从数据库中获取结果

mymongocollection.AsQueryable().Where(x => x.Type == 1);

现在我想从上面返回20条随机记录。我一直在寻找,但我找不到用LINQ做这个的正确方法。我不想在内存中,而是在数据库上。我发现你可以使用MongoDB的$sample聚合,但我不知道如何将它转换成LINQ(如果它甚至可能)。

4 个答案:

答案 0 :(得分:7)

我猜你正在使用不正确的命名空间,例如使用System.Linq;来提供对IQueryable的访问权限。

您应该使用using MongoDB.Driver.Linq;来访问MongoQueryable具有sample聚合

的实施

您可以在2.4.0驱动程序版本中尝试以下聚合。

using MongoDB.Driver.Linq; 
collection.AsQueryable().Where(x => x.Type == 1).Sample(20); 

输出

{aggregate([{ "$match" : { "Type" : 1 } }, { "$sample" : { "size" : NumberLong(20) } }])}

参考这里

https://jira.mongodb.org/browse/CSHARP-1773

https://jira.mongodb.org/browse/CSHARP-1366

答案 1 :(得分:1)

我选择了完整的LINQ解决方案。唯一的问题是mongo没有让我按非属性排序所以我不得不提前调用toList来实现查询。

选择此答案支持的随机结果:Select N Random Records with Linq

var result = MongoCollection
            .AsQueryable()
            .Where(x => x.Type == 1)
            .ToList()
            .OrderBy(x => Guid.NewGuid())
            .Take(20)
            .ToList();

希望它有所帮助!

我认为这将在db中执行(如果我错了,请纠正我):

var result = MongoCollection
            .AsQueryable()
            .Where(x => x.Type == 1)
            .AsEnumerable()
            .OrderByDescending(x => Guid.NewGuid())
            .Take(20)
            .ToList();

稍微改善但仍在记忆中执行。

答案 2 :(得分:1)

您可以尝试跳过随机数量的结果。

var resultsCount = MongoCollection
                  .AsQueryable()
                  .Where(x => x.Type == 1)
                  .Count();

var randomSkip = (new Random()).Next(0, resultsCount - 20);

var result = MongoCollection
            .AsQueryable()
            .Where(x => x.Type == 1)
            .Skip(randomSkip)
            .Take(20)
            .ToList();

答案 3 :(得分:1)

扩展随机概念,可以创建一组随机索引

首先,找到总结果集大小:

this.userDoc = afDs.doc<User>('users/NaGjauNy3vYOzp759xsc');
 this.userDoc.valueChanges()
 .pipe(take(1))
 .subscribe(v => {
   this.user = v;
 })

然后创建随机索引:

var resultsCount = MongoCollection
  .AsQueryable()
  .Where(x => x.Type == 1)
  .Count();

然后通过压缩来应用于查询:

var sampleSize = 10;
var rnd = new Random();
var indexes = Enumerable.Range(0, resultsCount-1);
var randomSet = indexes
  .OrderBy(r => rnd.NextDouble())
  .Take(sampleSize)
  .ToList();

它应该在内存方面有效,但在网络方面则不然。

这是对带有模拟数据库项目的Linqpad的测试:

var result = MongoCollection
  .AsQueryable()
  .Where(x => x.Type == 1)
  .Zip(indexes, (x, y)=> Tuple.Create(x,y))
  .Where(tuple => randomSet.Any(r => r == tuple.Item2))
  .Take(sampleSize)       // for good measure, finish when all samples taken
  .Select(t => t.Item1)   // clear the indexes
  .ToList();