Search code examples
c#asp.netmongodbmongodb-querymongodb-.net-driver

Query MongoDB C#: how can I extract in a BsonDocument the field that results from calling aggregate method?


I have 2 collections "images" and "user_preff".

In my app:

  • "images" contains "file_name" and "data"(byte array)
  • "user_preff" contains "username"(user that liked that image) and "file_name"

What I would like to do is to join this collection and I want to display the images that user liked.

I am using this one :

var documents = collection.Aggregate().Match(filter).Lookup("images", "file_name", "file_name", "common").As<BsonDocument>().Match(new BsonDocument()).ToList();

Now in the field common is what I want. How can I extract that data into another BsonDocument?


Solution

  • You can store your binary as BinData, and read the values with the following code. Projection used to select the data column and rename the field, if that's needed.

    string connectionString = "mongodb://localhost:27017";
    var client = new MongoClient(connectionString);
    var db = client.GetDatabase("test");
    //var images = db.GetCollection<BsonDocument>("images");
    var userPreff = db.GetCollection<BsonDocument>("user_preff");
    //images.InsertOne(BsonDocument.Parse("{\"file_name\": \"bus.jpg\", \"data\": BinData(0, \"...\")}"));
    //userPreff.InsertOne(BsonDocument.Parse("{\"username\": \"ntohl\", \"file_name\": \"bus.jpg\"}"));
    var filter = Builders<BsonDocument>.Filter.Empty;
    var documents = userPreff.Aggregate().Match(filter).Lookup("images", "file_name", "file_name", "common")
        .Project("{\"imagesOfUser\": \"$common.data\"}").ToCursor();
    while (documents.MoveNext())
    {
        foreach (BsonDocument bsonDocument in documents.Current)
        {
            foreach (var image in bsonDocument["imagesOfUser"].AsBsonArray)
            {
                byte[] bytes = image.AsBsonBinaryData.Bytes;
            }
        }
    }
    

    You can get away with a simpler projection if rename is not needed:

    var documents = userPreff.Aggregate().Match(filter).Lookup("images", "file_name", "file_name", "common")
        .Project("{\"_id\": 0, \"common.data\": 1}").ToCursor();
    while (documents.MoveNext())
    {
        foreach (BsonDocument bsonDocument in documents.Current)
        {
            foreach (var common in bsonDocument["common"].AsBsonArray)
            {
                byte[] bytes = common["data"].AsBsonBinaryData.Bytes;
            }
        }
    }