6

I have a document type with some attributes, one of which is a Dictionary< string, string >.

Serialization and De-serealization seem to work fine (I can search, perform CRUD operations, etc.). The problem is that I'm trying to write a method to find all the objects of that type where the dictionary contains a specific value (id) among its Keys.

Attempted Query:

var objectCollection = db.GetCollection<MyClass>("MyClass");

var query = Query<MyClass>.Where(m => m.MyDictionary.Any(k => k.Key == id));

The Class:

public class MyClass
{

    public ObjectId Id { get; set; }
    // ...
    [BsonElement("Dictionary")]
    public Dictionary<string, string> MyDictionary { get; set; }
}

...but I get this Exception while building the query:

Any requires that the serializer specified for Dictionary support items by implementing 
MongoDB.Bson.Serialization.IBsonArraySerializer and returning a non-null result. 
MongoDB.Bson.Serialization.Serializers.DictionarySerializer`2[System.String,System.String] 
is the current serializer.

I suspect the problem is related to the fact that the c# driver's default serializer doesn't support this. Is there a workaround?

I've also tried to perform a "Contains" for the id string on the Dictionary.Keys collection, but that gives a NotSupportedException: Unable to determine the serialization information for the expression: m.Dictionary.Keys.

user1987392
  • 3,921
  • 4
  • 34
  • 59
  • Maybe you could try converting the m.MyDictionary.Keys to a list first before putting into the linq? var listOfKeys = m.Dictionary.Keys.ToList(); – DLeh Apr 07 '14 at 12:35
  • Nope: `NotSupportedException: Unable to determine the serialization information for the expression: Enumerable.ToList(m.Dictionary.Keys).` too. – user1987392 Apr 07 '14 at 12:41

1 Answers1

6

Figured it out on my own...

Added an annotation in MyClass to specify how I want the Dictionary to be serialized (read about DictionarySerializationOptions here for more info).

[BsonElement("Dictionary")]
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] // Added This!
public Dictionary<string, string> Dictionary { get; set; }

This serializes the Dictionary as an array of Documents, each containing a "k" (key) and "v" (value).

Then I changed my query to:

var query = Query.ElemMatch("Dictionary", Query.EQ("k", id));

This searches entries in my collection in which the Dictionary contains id as one of its keys.

Other relevant links:

Community
  • 1
  • 1
user1987392
  • 3,921
  • 4
  • 34
  • 59