2017-10-07 14 views
4

私は今、私は上から20件のランダムなレコードを返すしたいデータベースMongoDBのランダムな結果

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

から私の結果を得るためにMongoDBのLINQのドライバを使用しています。私は検索してきましたが、LINQでこれを行う適切な方法を見つけることができません。私はメモリではなく、データベースでそれを行うことを好む。私はあなたがMongoDBの$sample集約を使用できることを発見しましたが、これをLINQに変換する方法がわかりません(もし可能であれば)。

+0

あなたはhttps://stackoverflow.com/questions/35990720/having-difficulty-using-mongodb([こちら]投稿解決策を試してみました-c-sharp-drivers-sample?noredirect = 1&lq = 1)? – felix

+0

@felix私はそれを見ましたが、その解決策はLinqではありません。上記の私のコードステートメントから、私はLINQ Whereステートメントを保持している間に$サンプルをどのように追加できるのかよく分かりません。 – PoeHaH

答えて

5

私はあなたがIQueryableへのアクセスを提供System.Linq;を、使用してのような間違った名前空間を使用している推測しています。

あなたは代わりにあなたが2.4.0ドライバのバージョンに集約下に試すことができますsample集約

を持ってMongoQueryable実装にアクセスできるようになりますどのusing MongoDB.Driver.Linq;を使用する必要があります。

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

私は完全な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(); 

はそれが役に立てば幸い!

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

ほんの少し改善したが、まだメモリ内で実行:

私はこれが(私が間違っているなら、私を修正)デシベルで実行されることになると思います。

+3

OPは述べました*私はメモリでそれをしないことを好む* –

+0

マイクとの同意。私はこれが可能性であることを知っていますが、私はそれをメモリではしたくありません。基本的には、この問題に対するすべてのLINQの解決策があることを期待していますが、私はそこに何もないと思っています。 – PoeHaH

+0

ええ、私はあなたが非メモリー的な解決策を望んでいるのを見ましたが、全く解決策がなかったので、私はスタート= 1の方が好ましいとは思っていませんでした。おそらく、OrderByパーツのプロパティに基づいてランダムなハッシュを生成し、それに基づいてソートすると、データベース全体を実行できますか? – BOR4

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(); 
1

を出力し、インデックス

のランダムなセットを作成することができます

まず、総結果セットのサイズを見つける:それは効率的でなければなりません

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(); 

を:ビュンことで、クエリに適用されます次に

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

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

を次にランダムなインデックスを作成メモリワイズですが、ネットワークワイズではありません。

これは、シミュレートされたDB項目とLinqpadのためのテストです:

var resultsCount = 30; 
var sampleSize = 10; 

// Create a random set of indexes 
var rnd = new Random(); 
var indexes = Enumerable.Range(0, resultsCount-1); 
var randomSet = indexes.OrderBy(r => rnd.NextDouble()).Take(sampleSize).ToList(); 
randomSet.OrderBy(r => r).Dump("Random set of indexes"); 

// Simulated resultset 
// for convenience simulate db items from index set 
var db = indexes.Select(x => "Result" + x.ToString()); 

// The query 
var sampleOfResults = 
    db.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 

sampleOfResults.ToList().Dump("Sample"); 
関連する問題