1

I have documents that look like below:

{
    "_id" : ObjectId("58148f4337b1fc09b8c2de9k"),
    "Price" : 69.99,
    "Attributes" : [ 
        {
            "Name" : "Color",
            "Value" : "Grey",
        },
        {
            "Name" : "Gender",
            "Value" : "Mens",
        }
    ]
}

I am looking to get a distinct list of Attributes.Name (so if I just had the one document as above, I would get 'Color' and 'Gender' returned).

I was able to easily get what I needed through mongo shell (db.getCollection('myCollection').distinct('Attributes.Name'), but I'm really struggling with the C# driver (version 2.4). Can someone please help me translate the shell command to C#?

I tried something like below (and many variations). I'm new to the Mongo C# driver and am just feeling a bit lost. Any help would be appreciated.

var database = client.GetDatabase("mymongodb");
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("mycollection");
var filter = new BsonDocument();
var distinctAttributeNames = collection.Distinct<BsonDocument>("Attributes.Name", filter);
var tryAgain = collection.Distinct<BsonDocument>("{Attributes.Name}", filter);
1
  • What happens when you run the above code ? Check to make sure you have right collection/db name Commented Jun 15, 2017 at 21:14

1 Answer 1

5

There you go:

public class Foo
{
    public ObjectId Id;
    public double Price = 69.99;
    public Attribute[] Attributes = {
        new Attribute { Name = "Color", Value = "Grey" },
        new Attribute { Name = "Gender", Value = "Men" }
    };
}

public class Attribute
{
    public string Name;
    public string Value;
}

public class Program
{
    static void Main(string[] args)
    {
        MongoClient client = new MongoClient();
        var collection = client.GetDatabase("test").GetCollection<Foo>("test");
        collection.InsertOne(new Foo());
        var distinctItems = collection.Distinct(new StringFieldDefinition<Foo, string>("Attributes.Name"), FilterDefinition<Foo>.Empty).ToList();
        foreach (var distinctItem in distinctItems)
        {
            Console.WriteLine(distinctItem);
            // prints:
            // Color
            // Gender
        }
        Console.ReadLine();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for such a complete example. Stupid me though....I had it working, but I didn't realize I was getting the expected results returned, I only saw an InvalidOperation exception I was getting from the Mongo driver (which I forgot to mention in my question). I think the exception (which was just captured in the results, not thrown), was due to using the synchronous method and not calling 'ToList()'. I ended up using var distinctAttributeNames = collection.Distinct(new StringFieldDefinition<BsonDocument, string>("Attributes.Name"), new BsonDocument()).ToList();
Is there a way to get "Attributes.Name" strongly typed? I.e something like: new StringFieldDefinition<Foo, string>(x => x.Attributes.Name)?
@Bassebus: I don't think there is. What you could do, though, is use nameof() with a little bit of string fiddling (as in $"{nameof(Foo.Attributes)}.{nameof(Attribute.Name)}") which improves things a little bit here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.