Flutter如何遍历Cloud Firestore集合计算用户距离并触发近距离通知
Cloud Firestore 附近用户距离判定功能实现方案
前提准备
- 确保所有用户的Firestore文档中都存储了规范的经纬度字段,建议用官方
GeoPoint类型存储,也可拆分存为latitude(纬度,取值范围-9090)、`longitude`(经度,取值范围-180180)两个数值字段 - 提前向当前登录用户申请位置权限、通知权限,确保可以拿到用户实时定位、可以正常弹出通知提醒
- 从Firebase Auth模块获取到当前登录用户的唯一标识,用于过滤掉用户自己的记录
步骤1:拉取目标用户数据
如果你的项目用户量较小(千级以内),可以直接拉取除当前用户外的全量用户数据,以下为Web端JS示例,其他端逻辑一致仅语法调整:
import { getFirestore, collection, getDocs, query, where } from "firebase/firestore"; const db = getFirestore(); // 当前登录用户的uid,从Firebase Auth模块获取 const currentUid = "当前登录用户的uid"; // 构造查询条件,过滤当前用户自身的记录 const userQuery = query(collection(db, "users"), where("uid", "!=", currentUid)); const querySnapshot = await getDocs(userQuery);
步骤2:实现经纬度距离计算
使用Haversine公式计算两个经纬度点的球面距离,米级精度完全满足200m的判定需求:
/** * 计算两个经纬度点之间的距离 * @param {number} lat1 点1纬度 * @param {number} lon1 点1经度 * @param {number} lat2 点2纬度 * @param {number} lon2 点2经度 * @returns {number} 两点距离,单位为米 */ function calculateDistance(lat1, lon1, lat2, lon2) { const earthRadius = 6371e3; // 地球平均半径,单位米 const radLat1 = lat1 * Math.PI / 180; const radLat2 = lat2 * Math.PI / 180; const deltaLat = (lat2 - lat1) * Math.PI / 180; const deltaLon = (lon2 - lon1) * Math.PI / 180; const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return earthRadius * c; }
步骤3:距离判定与通知触发
遍历拉取到的用户数据,逐个计算与当前用户的距离,符合条件则触发通知:
// 当前用户的实时经纬度,从设备定位模块获取 const currentLat = 39.9042; const currentLon = 116.4074; const nearUserList = []; querySnapshot.forEach(doc => { const userData = doc.data(); const distance = calculateDistance( currentLat, currentLon, userData.latitude, userData.longitude ); // 距离小于200米则加入附近用户列表 if (distance < 200) { nearUserList.push(userData); } }); // 存在附近用户时触发通知 if (nearUserList.length > 0) { // 可替换为对应端的推送通知接口,示例为Web端Notification API new Notification("附近用户提醒", { body: `当前有${nearUserList.length}位用户在你周边200米范围内` }); }
性能优化建议
如果你的项目用户量超过千级,全量拉取数据会产生大量不必要的性能损耗和计费开销,建议做以下优化:
- 用GeoHash对经纬度进行编码后存储在Firestore中,查询时仅拉取当前用户所在GeoHash区块以及相邻8个区块的用户,大幅减少拉取的数据量
- 配合Cloud Functions实现后端计算,仅将符合距离条件的用户数据返回给前端,减少前端计算压力
相关教程说明
社区和官方文档都有大量对应功能的实现演示,搜索Firestore地理位置范围查询、附近用户功能实现即可找到对应的文字和视频教程。
内容的提问来源于stack exchange,提问作者Joseph Chong
相关产品推荐
相关产品推荐

