将 Mongodb 中的日期与 C# LINQ 驱动程序进行比较

Posted

技术标签:

【中文标题】将 Mongodb 中的日期与 C# LINQ 驱动程序进行比较【英文标题】:Comparing dates in Mongodb with C# LINQ driver 【发布时间】:2016-11-04 13:50:03 【问题描述】:

我有一个 MongoDB 集合,其中包含一个表示日期的字符串字段。在我的 C# 应用程序中,我将结果映射到具有聚合字段的类,该聚合字段将该字符串转换为 DateTime 对象

[BsonIgnoreExtraElements]
public class Tweet

    public ObjectId Id  get; set; 

    [BsonElement("text")]
    public string Texto  get; set; 

    [BsonElement("created_at")]
    public string Fecha  get; set; 

    public DateTime FechaConvertida
    
        get
        
            var formato = "ddd MMM dd HH:mm:ss zzzz yyyy"; //'Sun Oct 23 19:42:04 +0000 2016'
            var enUS = new CultureInfo("en-US");
            var fechaConvertida = DateTime.ParseExact(this.Fecha, formato, enUS, DateTimeStyles.None);
            return fechaConvertida;
        
    

然后在我的 api 上查询过滤两个日期之间的元素(使用“CSharp Driver LINQ”)

public IEnumerable<Tweet> GetTweetsDePeriodo(string nombreColeccion, int dias)
    
        var hoy = DateTime.Today;
        var fechaInicial = hoy.AddDays(-dias);

        var coleccion = _db.GetCollection<Tweet>(nombreColeccion).AsQueryable<Tweet>();
        var tweetsFiltrados = (from c in coleccion
                               where c.FechaConvertida >= fechaInicial
                               select c
                               ).ToList();
        return coleccion;
    

然后我收到以下错误: *处理请求时发生未处理的异常。 InvalidOperationException: document.FechaConvertida 不受支持

有什么想法吗? 提前致谢,

【问题讨论】:

你能将 fechaInicial 声明为 DateTime 而不是 var。 你能告诉我们你的推文数据对象吗? @viveknuna 我试过了,但没有改变任何东西。无论如何,谢谢, @Dudemanword 推文数据对象是一个大 json,实际上它只是返回 Twitter API 的对象。在这种情况下,相关的是在“Created_at”字段中返回的带有日期的字符串的格式,这很奇怪:“Sun Oct 23 19:42:04 +0000 2016”。我认为这是主要问题,因为库无法解析它。感谢您的帮助。 【参考方案1】:

最后,我找到了一个使用自定义序列化程序来处理日期字段的解决方案。这就是它的样子。

我的班级:

[BsonIgnoreExtraElements]
public class Tweet

    public ObjectId Id  get; set; 

    [BsonElement("text")]
    public string Texto  get; set; 

    [BsonElement("created_at")]
    [BsonSerializer(typeof(FechaTweetsSerializer))]
    public DateTime Fecha  get; set; 

还有我的自定义序列化器:

public class FechaTweetsSerializer : SerializerBase<DateTime>


    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value)
    
        context.Writer.WriteString(value.ToString(CultureInfo.InvariantCulture));
    

    public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    
        var fecha = context.Reader.ReadString();
        return ConvertirFecha(fecha);
    

    private DateTime ConvertirFecha(string fechaFormatoTwitter)
    
        var formato = "ddd MMM dd HH:mm:ss zzzz yyyy"; //'Sun Oct 23 19:42:04 +0000 2016'
        var enUS = new CultureInfo("en-US");
        var fechaConvertida = DateTime.ParseExact(fechaFormatoTwitter, formato, enUS, DateTimeStyles.None);
        return fechaConvertida;
    

希望它对某人有所帮助。

【讨论】:

【参考方案2】:

正如 cmets 中已经提到的,如果您要在模型中将属性声明为日期时间

[BsonElement("created_at")]
public DateTime Fecha  get; set; 

那么这应该不是问题。您还可以使用 BsonRepresentation 装饰您的财产,以确保发生正确的(反)序列化

[BsonRepresentation(BsonType.DateTime)]
[BsonElement("created_at")]
public DateTime Fecha  get; set; 

为了执行您的查找,一个简单的解决方案是

var coleccion = _db.GetCollection<Tweet>(nombreColeccion).Find(x => x.Fecha >= fechaInicial).ToList();

创建一个 c# 属性来将字符串解析为日期,然后在您的过滤器中引用该属性将不起作用,因为转换不是在数据库范围内发生,而是在 c# 代码中发生。如果将日期存储为 DateTime (MongoDb ISODate()) 不是一个选项,您可以查看 Project() 以从字符串中投影转换后的日期,然后执行查询

【讨论】:

我尝试将该字段声明为 DateTime 并添加了“BsonRepresentation”标签,但它引发了异常:FormatException: String was not Recognized as a valid DateTime问题是存储在 BD 中的字符串具有奇怪的日期时间格式:'Sun Oct 23 19:42:04 +0000 2016'。你知道一种“即时”序列化的方法吗?也许是一个自定义的 Bson 序列化器?感谢您的帮助

以上是关于将 Mongodb 中的日期与 C# LINQ 驱动程序进行比较的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 保存到 SQL 中的 DATE 类型列 - Linq to SQL

使用 Linq C# 获取元组对象列表中的最新日期对象

使用 C# 、 LINQ 进行排序

在 C# 代码中的 DB 中的 Linq 查询中包含空单元格

C# - LINQ - 按日期范围分组集合

使用 LINQ C# 将公共数据分组到新字符串中