C# Linq (driver 2.2): querying documents with specific Dictionary items

2,266 views
Skip to first unread message

Kevin Versfeld

unread,
Feb 8, 2016, 8:42:22 AM2/8/16
to mongodb-user
Hi all

Using the latest C# driver for MongoDB. Have the following kind of structure:
    class Person
    {
        public string Name { get; set; } //Mapped to "n"
        public Dictionary<string, string> StringValues { get; set; }  //Mapped to "sv"
    }


Sample doc inserted (via driver) into DB:
    "_id" : "56b89040e73e5757443d6c6e", 
    "n" : "Kevin", 
    "sv" : [
        {
            "k" : "k1", 
            "v" : "1"
        }, 
        {
            "k" : "k2", 
            "v" : "2"
        }, 
    ]
}

So, I want to find documents in my Person collection which have particular items in StringValues ("sv"). 
On thing I tried was this:  
...Where(p => p.StringValues.Any(sv => sv.Key == "k1"));

But got this error:  
"The expression tree is not supported: {document}{sv}"


In older versions of the driver (1.4 if I recall) I was building up a nice complicated thing using the Query helpers, .ElemMatch etc etc, but also injecting that into a LINQ expression using the .Inject extension method (which doesn't work anymore/is deprecated I believe). Long story.... :)

Not sure if relevant, but my conventions for generic dictionaries gos a little something like this:
                    var serializer = memberMap.GetSerializer();
                    var dicSerial = serializer as IDictionaryRepresentationConfigurable;
                    if (dicSerial != null)
                    {
                        memberMap.SetSerializer(dicSerial.WithDictionaryRepresentation(DictionaryRepresentation.ArrayOfDocuments));
                    }





Wan Bachtiar

unread,
Feb 20, 2016, 8:01:43 AM2/20/16
to mongodb-user

So, I want to find documents in my Person collection which have particular items in StringValues (“sv”).

Hi Kevin,

You could try adding an extra mapping for StringValues to list the name the fields for k and v. For example:

public class Person
{
    public string Name; //Mapped to "n"
    public IEnumerable<StringValue> StringValues { get; set; }  //Mapped to "sv"
}
public class StringValue
{
    public string Key; //Mapped to 'k'
    public string Value; //Mapped to 'v'
}

Then to query a document in Person collection where Key matching certain values you could do:

var query = collection.AsQueryable<Person>()
            .Where(p => p.StringValues.Any(s => s.Key == "k1"));

The above snippet was tested in .Net v4.5.2 and mongocsharpdriver-2.2.3.

You may also find the examples in MongoDB C# driver LINQ useful.

Regards,

Wan.

Kevin Versfeld

unread,
May 16, 2016, 6:16:58 AM5/16/16
to mongodb-user
Fantastic! Thanks Wan, that works like a charm (apologies for the long delay - project issues meant this work was on hold for a few months for me,  unfortunately)
Reply all
Reply to author
Forward
0 new messages