我正在使用MongoDB的linq驱动程序从数据库中获取结果
mymongocollection.AsQueryable().Where(x => x.Type == 1);
现在我想从上面返回20条随机记录。我一直在寻找,但我找不到用LINQ做这个的正确方法。我不想在内存中,而是在数据库上。我发现你可以使用MongoDB的$sample
聚合,但我不知道如何将它转换成LINQ(如果它甚至可能)。
答案 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) } }])}
参考这里
答案 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();