I'm new with Mongo DB and I'm trying to figure out how to do some more complex queries. I have a document that has a nested array of DateTime.
Here is my data:
{ "_id" : ObjectId("537d0b8c2c6b912520798b76"), "FirstName" : "Mary", "LastName" : "Johnson", "Age" : 27, "Phone" : "555 555-1212", "Dates" : [ISODate("2014-05-21T21:34:16.378Z"), ISODate("1987-01-05T08:00:00Z")] }
{ "_id" : ObjectId("537e4a7e2c6b91371c684a34"), "FirstName" : "Walter", "LastName" : "White", "Age" : 52, "Phone" : "800 123-4567", "Dates" : [ISODate("1967-12-25T08:00:00Z"), ISODate("2014-12-25T08:00:00Z")] }
What I want to do is return the document where the Dates array contains a value between a range. In my test case the range is 1/1/1987 and 1/10/1987 so I expect to get back the first document listed above (Mary Johnson) because 1/5/1987 is in that Dates array and falls between 1/1/1987 and 1/10/1987.
I'd like to be able to do this with both the MongoDB command line utility and the C# driver.
With the C# driver I tried the following LINQ query (based on an example in the MongoDB documentation):
DateTime beginRange = new DateTime(1987, 1, 1);
DateTime endRange = new DateTime(1987, 1, 10);
var result = from p in people.AsQueryable<Person>()
where p.Dates.Any(date => date > beginRange && date < endRange)
select p;
The above code throws an exception from within the C# Driver code:
Any is only supported for items that serialize into documents. The current serializer is DateTimeSerializer and must implement IBsonDocumentSerializer for participation in Any queries.
When I try and query the MongoDB database directly I tried the following:
db.People.find( {Dates: { $gt: ISODate("1987-01-01"), $lt: ISODate("1987-01-10") } } )
This query results in both of the documents coming back instead of just the one that has 1/5/1987 in its Dates array.
EDIT:
I figured out a way to do if from the C# driver. It isn't as clean as I would like but it is doable.
I figured that since there was a way to get what I wanted directly from the command utility that there must be a way to do if from the C# driver as well by just executing the same query from the C# driver.
string command = "{Dates : { $elemMatch : { $gt: ISODate(\"" + beginRange.ToString("yyyy-MM-dd") + "\"), $lt: ISODate(\"" + endRange.ToString("yyyy-MM-dd") + "\") } } } ";
var bsonDoc = BsonSerializer.Deserialize<BsonDocument>(command);
var queryDoc = new QueryDocument(bsonDoc);
MongoCursor<Person> p = people.Find(queryDoc);