如何在Firestore中按日期跟踪并更新计步器项目的对应文档?
问题核心原因
- 遍历逻辑错误:你在遍历文档的循环中,只要遇到第一个非当日的文档,就会直接触发新建逻辑并终止遍历,完全不会检查剩余文档中是否存在当日对应的文档,导致每次都会重复新建。
- 日期格式化存在本地化风险:你使用的
E, MMM dd yyyy格式包含星期、月份的本地化缩写,当用户系统语言和你生成日期时的语言不一致时,两个实际同一天的日期字符串会对比失败。 - 查询效率极低:每次点击都拉取整个步数集合的所有文档再遍历,数据量大之后会严重影响性能且浪费流量。
修复方案
1. 优先优化日期标识格式
把日期标识换成无本地化风险的纯数字格式,比如yyyyMMdd(示例:20240520),完全规避语言差异导致的对比失败问题。
2. 优化Firestore查询逻辑
直接查询匹配当日日期的文档,不需要拉取全量数据遍历:
修改后的参考代码
mSaveDataToFireStore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String stepCountNum = mTV_StepCounter.getText().toString(); String stepCountMeter = mTV_StepCounter_meter.getText().toString(); String stepCalories = mCalories_Burn.getText().toString(); String stepDuration = mCounter_Duration.getText().toString(); // 统一指定Locale.US避免本地化差异,也可以直接换成yyyyMMdd纯数字格式更稳妥 DateFormat dateFormat = new SimpleDateFormat("E, MMM dd yyyy", Locale.US); Date date = new Date(); String todayDateStr = dateFormat.format(date); Calendar callForDate = Calendar.getInstance(); SimpleDateFormat currentDay = new SimpleDateFormat("E", Locale.US); String saveCurrentDay = currentDay.format(callForDate.getTime()); SimpleDateFormat currentTime = new SimpleDateFormat("HH:mm:ss a", Locale.US); String saveCurrentTime = currentTime.format(callForDate.getTime()); FirebaseUser AppUser = FirebaseAuth.getInstance().getCurrentUser(); if (AppUser == null) return; String userId = AppUser.getUid(); CollectionReference colRef = FirebaseFirestore.getInstance() .collection("REGISTERED USERS").document(userId) .collection("STEP COUNTER"); // 直接查询当日的文档,不用拉全量集合 colRef.whereEqualTo("mStepDate", todayDateStr) .get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot queryDocumentSnapshots) { StepCounter_Model stepCountUpdate = new StepCounter_Model(todayDateStr, saveCurrentDay, saveCurrentTime, stepCountNum, stepCountMeter, stepCalories, stepDuration); if (!queryDocumentSnapshots.isEmpty()) { // 存在当日文档,直接更新 DocumentSnapshot doc = queryDocumentSnapshots.getDocuments().get(0); Map<String, Object> saveInfo = new HashMap<>(); saveInfo.put("mStepDate", stepCountUpdate.mStepDate); saveInfo.put("mStepDay", stepCountUpdate.mStepDay); saveInfo.put("mStepTime", stepCountUpdate.mStepTime); saveInfo.put("mStepCount", stepCountUpdate.mStepCount); saveInfo.put("mStepCountMeter", stepCountUpdate.mStepCountMeter); saveInfo.put("mStepCalories", stepCountUpdate.mStepCalories); saveInfo.put("mStepDuration", stepCountUpdate.mStepDuration); colRef.document(doc.getId()).update(saveInfo); Toast.makeText(StepTrackerActivity.this, "数据更新成功", Toast.LENGTH_SHORT).show(); } else { // 不存在当日文档,新建 addTo_FireStoreDB(todayDateStr, saveCurrentDay, saveCurrentTime, stepCountNum, stepCountMeter, stepCalories, stepDuration); Toast.makeText(StepTrackerActivity.this, "今日数据已保存", Toast.LENGTH_SHORT).show(); } } }); } });
额外优化建议
可以直接用日期字符串作为Firestore文档的ID,比如文档ID直接设为20240520这种格式,不需要查询,直接用set方法传入SetOptions.merge()就能自动实现存在则更新、不存在则新建的逻辑,代码更简洁效率也更高:
// 示例用yyyyMMdd当文档ID SimpleDateFormat idFormat = new SimpleDateFormat("yyyyMMdd", Locale.US); String docId = idFormat.format(new Date()); colRef.document(docId).set(stepCountUpdate, SetOptions.merge());
内容的提问来源于stack exchange,提问作者kels_osas888
相关产品推荐
相关产品推荐

