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

标签 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 属性不会存储在数据库中。从数据库中读取文档也失败。

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 对象,并使用序列化值来过滤数据库本身中的结果。

最佳答案

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

之前,查询不会运行

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

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

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

如果您想控制序列化的内容,即如果您的类本质上只包含一个日期时间,为什么不存储 UTC 日期时间戳并为其他属性使用 BsonIgnore

关于c# - 自定义序列化程序如何影响搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18198300/

相关文章:

c# - 如何在asp.net中制作多语言网站

javascript - Passportjs 类型错误 : undefined is not a function

javascript - Mongo 拉入 Meteor 不拉动

java - MySQL、MongoDB、RabbitMQ 的事务原子性

timezone - 将时区 ID 存储在数据库中是否安全,或者它们可以更改吗?

c# - 来自 Week 和 WeekYear 的 LocalDate

c# - MVC Telerik 网格格式列 bool 到字符串

javascript - Microsoft JScript 运行时错误 : Cannot assign to a function result?

c# - 如何配置 Ninject 以注入(inject) NodaTime IClock

c# - 如何在 PagedList.Mvc 中拥有多个 PagedListRenderOptions?