Home > other >  Is there a way to get a nullable value from a MongoDB C# driver projection with expression and dicti
Is there a way to get a nullable value from a MongoDB C# driver projection with expression and dicti

Time:09-28

Lets say I have these classes:

public class Foo
{
   public IReadonlyDictionary<string, DateTime> Values { get; set; }
}

public class Bar
{
   public Foo Foo { get; set; }
}

Now if I do this projection:

var projection = Builders<Bar>.Projection.Expression(x => x.Foo.Values["key"])

I will get DateTime.MinValue and not a null in case the element key does not exist in the dictionary. The value itself indeed cannot be null (and I assume that is why MongoDB is doing default(DateTime)), but it can happen that it does not exist in the dictionary.

I am wondering if there is a good way to tell MongoDB that the result should be DateTime? so that I can get a null in case the element does not exist.

P.S. I can make the dictionary value DateTime?, and that will work but I would rather avoid it, since the Value itself should not ever be null.

Sample documents:

// With values
{
  "_t": "Bar",
  "Foo":
    {
      "1521": "2022-09-26T08:25:38.502 00:00"
    }
}

// Empty
{
  "_t": "Bar",
  "Foo":
    {
    }
}

CodePudding user response:

The following query returns the values as DateTime?; if there is no Foo, it is null, if it is set, it returns the value:

var bars = await (await barColl.FindAsync(
  Builders<Bar>.Filter.Empty, 
  new FindOptions<Bar, DateTime?>()
  {
    Projection = Builders<Bar>.Projection.Expression(
      x => (DateTime?) (x.Foo == null ? null : x.Foo.Value))
  })).ToListAsync();

For the following documents

{ "_id": { "$oid": "632dc047e08f08bfaeabc2d6" }, "Foo": null}
{ "_id": { "$oid": "632dc047e08f08bfaeabc2d7" }, "Foo": { "Value": { "$date": {  "$numberLong": "1663942727428" } } }}

the result is

null
2022-09-23T14:18:47Z

Update: Dictionary

If you want to project the DateTime from a Dictionary<string, DateTime>, you can use the following expression with a ternary operator that checks against default(DateTime):

var projection = Builders<SoNullableDt>.Projection
  .Expression<DateTime?>(
    x => x.Foo["1521"] == default(DateTime) ? null : x.Foo["1521"]);
var result = await (await coll.FindAsync(Builders<SoNullableDt>.Filter.Empty, 
  new FindOptions<SoNullableDt, DateTime?>() { Projection = p })).ToListAsync();

Based upon the sample documents (with the datetime changed to a Date data type in MongoDB), this finds the following data:

26.09.2022 08:25:38
null
  • Related