You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BSON文档字符串转DateTime:MongoDB嵌套数组日期过滤问题求助

解决MongoDB嵌套数组的日期范围过滤问题

文档结构

MongoDB中存储的文档对应以下C#实体类:

public class BookingDocument{
     public string Id {get;set;}
     public List<ActivityDocument> Activities {get;set;}
     public string Status {get;set;}
}

public class ActivityDocument {
  public string DateFrom {get;set;}
  public string Status {get;set;}
}

当前处理逻辑

已实现的日期转换逻辑如下:

public async Task<List<BookingDocument>> ActivityBookingList(string start,string end) 
{
    DateTime startDate;
    DateTime endDate;

    startDate = DateTime.ParseExact(start + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    endDate = DateTime.ParseExact(end + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    
    // 待补充过滤逻辑
}

遇到的问题

尝试三种过滤方案均存在异常:

  • 方案1:使用$dateFromString时,报错"$dateFromString only supports an object as an argument, found: string"
  • 方案2:使用$toDate时,报错"Unsupported conversion from array to date in $convert with no onError value"
  • 方案3:可返回结果,但仅检查Activities数组的第一个元素

解决方案

核心需求是过滤出至少包含一个Activity的DateFrom落在指定日期范围内的BookingDocument,需正确处理字符串转日期并遍历数组所有元素,以下是基于MongoDB .NET驱动的实现:

public async Task<List<BookingDocument>> ActivityBookingList(string start, string end)
{
    DateTime startDate = DateTime.ParseExact(start + " 00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    DateTime endDate = DateTime.ParseExact(end + " 00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);

    // 构建聚合管道
    var pipeline = new BsonDocument[]
    {
        new BsonDocument("$match", new BsonDocument
        {
            { "Activities", new BsonDocument("$elemMatch", new BsonDocument
                {
                    { "$expr", new BsonDocument("$and", new BsonArray
                        {
                            // 转换DateFromString并判断是否大于等于起始日期
                            new BsonDocument("$gte", new BsonArray
                            {
                                new BsonDocument("$dateFromString", new BsonDocument
                                    {
                                        { "dateString", "$DateFrom" },
                                        { "format", "%Y-%m-%d" } // 需与DateFrom存储的格式一致,若带时间则改为"%Y-%m-%d %H:%M:%S"
                                    }),
                                startDate
                            }),
                            // 转换DateFromString并判断是否小于等于结束日期
                            new BsonDocument("$lte", new BsonArray
                            {
                                new BsonDocument("$dateFromString", new BsonDocument
                                    {
                                        { "dateString", "$DateFrom" },
                                        { "format", "%Y-%m-%d" }
                                    }),
                                endDate
                            })
                        })
                })
            }
        })
    };

    // 执行聚合查询并返回结果
    var collection = _mongoDatabase.GetCollection<BookingDocument>("BookingList");
    return await collection.Aggregate<BookingDocument>(pipeline).ToListAsync();
}

错误原因说明

  1. 方案1错误:$dateFromString要求传入包含dateString、format等字段的对象,而非直接传入字符串字段引用,正确写法应为$dateFromString: { dateString: "$DateFrom", format: "..." }
  2. 方案2错误:直接对Activities数组使用$toDate,而非数组中每个元素的DateFrom字段,导致MongoDB尝试将整个数组转换为日期,触发类型转换错误
  3. 方案3错误:未使用$elemMatch,直接通过Activities.DateFrom访问数组字段时,MongoDB默认仅检查数组第一个元素的对应字段

内容的提问来源于stack exchange,提问作者AG Mohamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 13:45:15