自定义序列化程序如何影响搜索?

时间:2013-08-12 23:28:25

标签: c# mongodb nodatime

我正在尝试在我的应用中使用NodaTime。该应用程序将数据保存在mongodb数据库中。考虑以下课程

public class SomeType
{
    public ObjectId Id { get; set; }
    public Instant Instant { get; set; }
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
    public DateTime DateTime { get; set; }
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime DateTimeUtc { get; set; }
//    public ZonedDateTime ZonedDateTime { get; set; }
//    public LocalDateTime LocalDateTime { get; set; }
}

如果不添加自定义序列化程序,则类的Instant属性不会存储在db中。从数据库中读取文档也会失败。

public class InstantBsonSerializer : BsonBaseSerializer
{
    public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
    {
        var ticks = bsonReader.ReadInt64();
        return new Instant(ticks);
    }

    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        var ticks = bsonReader.ReadInt64();
        return new Instant(ticks);
    }

    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        var instant = (Instant) value;
        bsonWriter.WriteInt64(instant.Ticks);
    }
}

我创建了上面的序列化程序并正确注册了它。我现在能够使用Instant的正确值设置保存和检索我的类的实例。

我的问题是C#驱动程序如何使用linq处理搜索?

var list = mongoDatabase.GetCollection<SomeType>("SomeType")
                     .AsQueryable<SomeType>()
                     .Where(x => x.Instant < Instant.FromDateTimeUtc(dateTime.ToUniversalTime()))
                     .ToList();
Console.WriteLine(list.Count);

我得到了正确的文件清单。 我试图了解mongodb如何获取此数据。它首先加载所有数据,正确反序列化然后过滤?或者它是否序列化where子句的Instant值并使用序列化值过滤所有文档,加载匹配的文档然后反序列化?

我试过看到mongodb探查器记录的查询,但它似乎没有记录任何东西。我已将分析级别设置为2。

对于Instant,序列化值为long。但是在ZonedDateTime的情况下,序列化值将是具有两个属性的文档。在这种情况下如何搜索工作?

修改

我能够使分析工作。以下c#查询,

mongoDatabase.GetCollection<SomeType>("SomeTypeCollection")
             .AsQueryable<SomeType>()
             .Where(x => x.Instant < Instant.FromDateTimeUtc(DateTime.UtcNow))
             .ToList();

导致以下mongodb查询

{ "Instant": { $lt: 13781017828460782 }} 

意思是,c#驱动程序序列化我的Instant对象并使用序列化值来过滤db本身的结果。

1 个答案:

答案 0 :(得分:1)

驱动程序会将linq查询转换为mongodb查询并在反序列化之前过滤结果。在您致电ToList()

之前,查询将无法运行

以下是受支持的运营商:http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/

在驱动程序从返回的数据开始构建对象图之前,自定义反序列化器不会发挥作用。

对于简单类型的类或者在阅读/编写文档时没有做额外工作的情况,通常不需要自定义序列化程序。

如果你想控制序列化的内容,即基本上你的类只保存一个日期时间,为什么不这样做才能存储UTC日期时间戳,并使用BsonIgnore来表示其他属性。