如何检查Firestore中是否已存在某些数据 [英] How to check a certain data already exists in firestore or not
问题描述
在将新数据添加到Firestore中之前,我想检查数据库中是否已经存在相同类型的数据.如果已经存在数据,则意味着我要防止用户在数据库中输入重复数据. 就我而言,这就像一个约会预订,如果已经存在同一时间的预订,我想防止用户在同一时间预订.我尝试使用查询功能,但并不能防止重复数据输入.有人请帮助我
Before adding a new data into the firestore, i want to check already a data of the same kind exists in the database or not.if already a data was present means i want to prevent the user from entering duplicate data in the database. In my case it is like a appointment booking if already a booking for the same time exists,i want to prevent to users to book on the same time.i tried using query function but it is not preventing duplicate data entering.someone plz help me
private boolean alreadyBooked(final String boname, final String bodept, final String botime) {
final int[] flag = {0};
CollectionReference cref=db.collection("bookingdetails");
Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (DocumentSnapshot ds : queryDocumentSnapshots) {
String rname, rdept, rtime;
rname = ds.getString("name");
rdept = ds.getString("dept");
rtime = ds.getString("time");
if (rdept.equals(botime)) {
if (rtime.equals(botime)) {
flag[0] = 1;
return;
}
}
}
}
});
if(flag[0]==1){
return true;
}
else {
return false;
}
}
推荐答案
从Cloud Firestore加载数据是异步进行的.从alreadyBooked
返回时,尚未加载数据,onSuccess
尚未运行,并且flag
仍具有其默认值.
Loading data from Cloud Firestore happens asynchronously. By the time you return from alreadyBooked
, the data hasn't loaded yet, onSuccess
hasn't run yet, and flag
still has its default value.
最简单的方法是使用一些日志语句:
The easiest way to see this is with a few log statements:
private boolean alreadyBooked(final String boname, final String bodept, final String botime) {
CollectionReference cref=db.collection("bookingdetails");
Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
System.out.println("Starting listener");
q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
System.out.println("Got data from Firestore");
}
});
System.out.println("Returning");
}
如果运行此代码,它将打印:
If you run this code it will print:
启动监听器
返回
从Firestore获取数据
Got data from Firestore
这可能不是您期望的顺序.但这完美地解释了为什么在调用alreadyBooked
时总是得到false
的原因:数据只是没有及时从Firestore返回.
That's probably not the order you expected. But it perfectly explains why you always get false
when calling alreadyBooked
: the data simply didn't come back from Firestore in time.
解决方案是更改您对问题的看法.您当前的代码具有逻辑:首先检查它是否已经预订,然后添加新项目".我们需要将其重新组织为:"开始检查它是否已经被预订.一旦知道不是,请添加一个新项目.在代码中,这意味着需要Firestore中的数据的所有代码都必须在onSuccess
内部或必须在其中调用.
The solution for this is to change the way you think about the problem. Your current code has logic: "First check if it is already booked, then add a new item". We need to reframe this as: "Start checking if it is already booked. Once we know that is isn't, add a new item." In code this means that all code that needs data from Firestore must be inside the onSuccess
or must be called from there.
最简单的版本是将代码移入 onSuccess
:
The simplest version is to move the code into onSuccess
:
private void alreadyBooked(final String boname, final String bodept, final String botime) {
CollectionReference cref=db.collection("bookingdetails");
Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
boolean isExisting = false
for (DocumentSnapshot ds : queryDocumentSnapshots) {
String rname, rdept, rtime;
rname = ds.getString("name");
rdept = ds.getString("dept");
rtime = ds.getString("time");
if (rdept.equals(botime)) {
if (rtime.equals(botime)) {
isExisting = true;
}
}
}
if (!isExisting) {
// TODO: add item to Firestore
}
}
});
}
虽然这很简单,但是它使alreadyBooked
的可重用性降低了,因为它现在也包含用于插入新项目的代码.您可以通过定义自己的回调接口来解决此问题:
While this is simple, it makes alreadyBooked
less reusable since now it contains the code to insert the new item too. You can solve this by defining your own callback interface:
public interface AlreadyBookedCallback {
void onCallback(boolean isAlreadyBooked);
}
private void alreadyBooked(final String boname, final String bodept, final String botime, AlreadyBookedCallback callback) {
CollectionReference cref=db.collection("bookingdetails");
Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (DocumentSnapshot ds : queryDocumentSnapshots) {
String rname, rdept, rtime;
rname = ds.getString("name");
rdept = ds.getString("dept");
rtime = ds.getString("time");
if (rdept.equals(botime)) {
if (rtime.equals(botime)) {
isExisting = true;
}
}
}
callback.onCallback(isExisting)
}
});
}
然后将其称为:
alreadyBooked(boname, bodept, botime, new AlreadyBookedCallback() {
@Override
public void onCallback(boolean isAlreadyBooked) {
// TODO: insert item
}
});
另请参阅(其中许多用于适用于相同逻辑的Firebase实时数据库):
Also see (many of these are for the Firebase Realtime Database, where the same logic applies):
- getContactsFromFirebase()方法返回空列表
- 道格关于异步的博客文章回调
- 在Firebase Listener中设置Singleton属性值
- Android + Firebase:同步为异步功能
- 是否可以从Firebase同步加载数据?
- 从firebase查询数据
- getContactsFromFirebase() method return an empty list
- Doug's blog post on asynchronous callbacks
- Setting Singleton property value in Firebase Listener
- Android + Firebase: synchronous for into an asynchronous function
- Is it possible to synchronously load data from Firebase?
- Querying data from firebase
这篇关于如何检查Firestore中是否已存在某些数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!