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; }
二、现有代码的不规范问题
_getData方法缺失await且空安全处理不当
当前代码未给readMongo添加await,导致values存储的是Future对象而非实际数据,且强制解包!会在异常场景下触发空指针。正确写法:Future<List<Map<String, dynamic>>> _getData() async { values = await MongoDatabase.readMongo(MongoDatabase.lessonCollection); return values ?? []; // 用空列表替代null,避免强制解包风险 }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(); }自定义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(), }; }数据转换流程不合理
当前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(); }空安全使用不严谨
代码中多处使用!强制解包(如id!.toMap()),若变量为null会直接抛出异常。应优先使用空安全运算符(如id?.toMap())或空合并运算符??处理null场景。
内容的提问来源于stack exchange,提问作者user14175926
相关产品推荐
相关产品推荐

