如何检查Firestore中是否已存在某些数据 [英] How to check a certain data already exists in firestore or not

查看:117
本文介绍了如何检查Firestore中是否已存在某些数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将新数据添加到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() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆