Geoflutterfire中isGreaterThan条件查询无结果问题求助
问题描述
我尝试用isGreaterThan条件查询时间字段,但始终获取不到数据。代码逻辑看起来没问题,但找不到问题根源。我需要展示时间大于所选时间的数据,怀疑问题出在Geoflutterfire与isGreaterThan条件的结合使用上。相关代码如下:
_setStream() async { _locationData = await location.getLocation(); var pos = await location.getLocation(); double lat = pos.latitude!; double lng = pos.longitude!; print('timeeeeeeeee$_time'); int _ti = Timestamp.now().millisecondsSinceEpoch - 999 * 60 * widget.time; var ref = await FirebaseFirestore.instance .collection('now') .where('gender', isEqualTo: widget.gender) .where('time', isGreaterThan: _ti) .orderBy('time', descending: true); GeoFirePoint center = geo.point(latitude: lat, longitude: lng); stream = radius.switchMap((rad) { var collectionReference = ref; return geo.collection(collectionRef: collectionReference).within( center: center, radius: rad, field: 'location', strictMode: true); }); setState(() { isLoading = false; }); stream = geo.collection(collectionRef: ref).within( center: center, radius: widget.distance, field: 'location', strictMode: true); stream!.listen((List<DocumentSnapshot> documentList) { documentList.forEach((element) { print("from data .......element"); print(element.data()); final data = element.data() as Map<String, dynamic>; final GeoPoint point = data['location']['geopoint']; print("from data .......latitude"); print(point.latitude); }); }); }
排查与解决方向
1. 时间戳类型不匹配
Firestore中time字段如果存的是Timestamp类型,直接用整数(millisecondsSinceEpoch)对比虽然能自动转换,但容易出问题,建议统一用Timestamp对象做比较:
// 转换为Timestamp类型再查询 Timestamp cutoffTime = Timestamp.fromMillisecondsSinceEpoch(_ti); var ref = FirebaseFirestore.instance .collection('now') .where('gender', isEqualTo: widget.gender) .where('time', isGreaterThan: cutoffTime) .orderBy('time', descending: true);
同时打印_ti和文档中的time字段值,确认你的时间范围计算是否正确——比如会不会_ti算出来的时间比所有文档的time都大,导致没有符合条件的数据。
2. 复合查询索引缺失
同时用gender、time和地理查询属于复合查询,必须在Firestore控制台创建对应索引。如果控制台有索引缺失的错误提示,直接点击提示里的链接一键创建即可。
3. 流被覆盖的问题
你代码里先给stream赋值了响应radius变化的流,之后又直接用固定半径的查询覆盖了它,导致第一个流完全失效。保留第一个赋值即可:
// 保留这个响应radius变化的流,删掉后面的stream覆盖代码 stream = radius.switchMap((rad) { return geo.collection(collectionRef: ref).within( center: center, radius: rad, field: 'location', strictMode: true); });
4. 严格模式的影响
strictMode: true会严格过滤地理范围,可能因为坐标精度问题过滤掉本该符合条件的数据。可以先改成strictMode: false测试,能拿到数据再调回严格模式。
调整后的测试代码
_setStream() async { _locationData = await location.getLocation(); var pos = await location.getLocation(); double lat = pos.latitude!; double lng = pos.longitude!; print('timeeeeeeeee$_time'); int _ti = Timestamp.now().millisecondsSinceEpoch - 999 * 60 * widget.time; Timestamp cutoffTime = Timestamp.fromMillisecondsSinceEpoch(_ti); print('截止时间:$cutoffTime'); // 打印确认时间范围 var ref = FirebaseFirestore.instance .collection('now') .where('gender', isEqualTo: widget.gender) .where('time', isGreaterThan: cutoffTime) .orderBy('time', descending: true); GeoFirePoint center = geo.point(latitude: lat, longitude: lng); // 保留响应radius变化的流 stream = radius.switchMap((rad) { return geo.collection(collectionRef: ref).within( center: center, radius: rad, field: 'location', strictMode: false, // 先关闭严格模式测试 ); }); stream!.listen((List<DocumentSnapshot> documentList) { print('查询到${documentList.length}条数据'); // 先看有没有数据 documentList.forEach((element) { print("文档数据:${element.data()}"); final data = element.data() as Map<String, dynamic>; print("文档time字段:${data['time']}"); // 和截止时间对比 final GeoPoint point = data['location']['geopoint']; print("纬度:${point.latitude}"); }); }); setState(() { isLoading = false; }); }
内容的提问来源于stack exchange,提问作者Mohammed Ali
相关产品推荐
相关产品推荐

