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

Flutter中通过Future过滤MongoDB数据及代码规范检查

Flutter 从 MongoDB 过滤拉取数据及代码规范优化

一、实现 MongoDB 数据过滤

1. 数据库层面过滤(推荐)

数据库层面过滤能减少网络传输的数据量,提升性能。你可以给readMongo方法添加过滤参数,利用MongoDB的查询语法实现精准筛选:

static Future<List<Map<String, dynamic>>> readMongo(
  dynamic collectionName, 
  {Map<String, dynamic>? filter} // 新增过滤条件参数
) async {
  // 根据是否有过滤条件执行不同查询
  final cursor = filter != null ? collectionName.find(filter) : collectionName.find();
  final data = await cursor.toList();
  return data;
}

过滤示例

  • 筛选info.semester为"2024春季"的课程:
Future<List<Map<String, dynamic>>> _getData() async {
  final filter = {"info.semester": "2024春季"};
  values = await MongoDatabase.readMongo(MongoDatabase.lessonCollection, filter: filter);
  return values ?? []; // 避免强制解包,返回空列表替代null
}
  • 筛选学分大于2的课程(使用MongoDB操作符):
final filter = {"info.credit": {"\$gt": 2}};
  • 筛选包含subjectId为1的课程:
final filter = {"subject.subjectId": 1};

2. 客户端过滤(仅小数据量场景使用)

如果无法在数据库层面过滤,可以拉取全量数据后在客户端筛选:

Future<List<LessonModel>> _getFilteredData() async {
  final allData = await MongoDatabase.readMongo(MongoDatabase.lessonCollection);
  // 先转成LessonModel列表再过滤
  final lessonList = allData.map((map) => LessonModel.fromMap(map)).toList();
  // 筛选指定条件的课程
  final filtered = lessonList.where((lesson) => lesson.info?.semester == "2024春季").toList();
  return filtered;
}

二、现有代码的不规范问题

  1. _getData方法缺失await且空安全处理不当
    当前代码未给readMongo添加await,导致values存储的是Future对象而非实际数据,且强制解包!会在异常场景下触发空指针。正确写法:

    Future<List<Map<String, dynamic>>> _getData() async {
        values = await MongoDatabase.readMongo(MongoDatabase.lessonCollection);
        return values ?? []; // 用空列表替代null,避免强制解包风险
    }
    
  2. readMongo参数未指定类型
    collectionName参数无类型声明,应根据使用的MongoDB库(如mongo_dart)指定具体类型,提升代码可读性与类型安全:

    static Future<List<Map<String, dynamic>>> readMongo(
      MongoCollection<Map<String, dynamic>> collectionName, 
      {Map<String, dynamic>? filter}
    ) async {
      final cursor = filter != null ? collectionName.find(filter) : collectionName.find();
      return await cursor.toList();
    }
    
  3. 自定义Id类冗余
    你实现的Id类完全可以用MongoDB官方库提供的ObjectId替代,它已封装$oid的序列化/反序列化逻辑:

    import 'package:mongo_dart/mongo_dart.dart';
    
    class LessonModel {
      LessonModel({this.id, this.info, this.subject});
    
      final ObjectId? id; // 替换自定义Id类
      final Info? info;
      final List<Subject>? subject;
    
      factory LessonModel.fromMap(Map<String, dynamic> json) => LessonModel(
            id: json["_id"] as ObjectId?,
            info: json["info"] == null ? null : Info.fromMap(json["info"]),
            subject: json["subject"] == null ? null : List<Subject>.from(json["subject"].map((x) => Subject.fromMap(x))),
          );
    
      Map<String, dynamic> toMap() => {
            "_id": id,
            "info": info?.toMap(),
            "subject": subject?.map((x) => x.toMap()).toList(),
          };
    }
    
  4. 数据转换流程不合理
    当前readMongo返回Map列表,后续需手动转成LessonModel,可直接在readMongo内完成转换,减少重复代码:

    static Future<List<LessonModel>> readMongo(
      MongoCollection<Map<String, dynamic>> collectionName, 
      {Map<String, dynamic>? filter}
    ) async {
      final cursor = filter != null ? collectionName.find(filter) : collectionName.find();
      final dataList = await cursor.toList();
      return dataList.map((map) => LessonModel.fromMap(map)).toList();
    }
    
  5. 空安全使用不严谨
    代码中多处使用!强制解包(如id!.toMap()),若变量为null会直接抛出异常。应优先使用空安全运算符(如id?.toMap())或空合并运算符??处理null场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:15:40