MongoDB: Using $sample with C# driver

2019-05-19 05:26发布

I'm trying to express the following query using the MongoDB C# driver (2.4.4):

db.media.aggregate({ $sample: { size: 1 }})

This what I have so far:

BsonDocument sample = new BsonDocument
{
    { "$sample", new BsonDocument { { "size", 1 } } }
};
MongoBlob mongoBlob = await _collection
    .Aggregate()
    .Group<MongoBlob>(sample)
    .FirstOrDefaultAsync();

I cannot put the sample to .Aggregate(AggregateOptions options = null) and putting it into the .Group(...) is obviously wrong. There is also no any like a .Sample() method.

Please, help. Thank you in advance.

2条回答
时光不老,我们不散
2楼-- · 2019-05-19 06:07

I believe it should be

MongoBlob mongoBlob = await _collection
    .Aggregate()
    .Sample(1)
    .FirstOrDefaultAsync();

If this doesn't work then let me know. Don't have windows system up right now to confirm

Edit (7-AUG):

Turns out its not that simple. The sample method doesn't exists in current driver. The classes which handle this are internal so no straight forward way to inherit. So worked out a solution based on reflection and a hack. Where you add a Stage to the pipeline and then edit it through reflection. Below is a working sample of my demo code

using System; using MongoDB.Bson; using MongoDB.Driver; using System.Reflection;

namespace TestMongo
{
    public static class MainClass
    {
        static IMongoClient _client;
        static IMongoDatabase _database;

        public static IAggregateFluent<BsonDocument> Sample(this IAggregateFluent<BsonDocument> agg, int count){
            var new_agg = agg.Skip(10);
            var stage =new_agg.Stages[new_agg.Stages.Count-1];
            var newDoc = new BsonDocument { 
                { "$sample", new BsonDocument {
                        {"size", count}
                    } } 
            };
            stage.GetType().GetField("_document"
             , BindingFlags.Instance | BindingFlags.NonPublic)
                 .SetValue(stage, newDoc);
            return new_agg;
        }

        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            _client = new MongoClient();
            _database = _client.GetDatabase("jobs");

            var col = _database.GetCollection<BsonDocument>("results");

            var agg = col.Aggregate().Sample(1);

            var data = agg.FirstOrDefault();
            data = null;
        }
    }
}
查看更多
老娘就宠你
3楼-- · 2019-05-19 06:14

Simply,

var randEl = await collection.AsQueryable().Sample(1).FirstOrDefaultAsync();

Do not forget add

using MongoDB.Driver.Linq;
查看更多
登录 后发表回答