2

我正在尝试在我的应用程序中使用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 如何获取这些数据。它是否首先加载所有数据,正确反序列化然后过滤?还是序列化Instantwhere 子句的值并使用序列化的值过滤所有文档,加载匹配的文档然后反序列化?

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

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

编辑:

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

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

导致以下 mongodb 查询

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

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

4

1 回答 1

1

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

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

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

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

如果您想控制序列化的内容,即如果您的类本质上只有一个日期时间,为什么不这样做,以便存储 UTC 日期时间戳并BsonIgnore用于其他属性。

于 2013-08-13T00:39:50.153 回答