如何检查某个数据是不是已存在于firestore中

Posted

技术标签:

【中文标题】如何检查某个数据是不是已存在于firestore中【英文标题】:How to check a certain data already exists in firestore or not如何检查某个数据是否已存在于firestore中 【发布时间】:2018-12-02 15:41:10 【问题描述】:

在将新数据添加到 Firestore 之前,我想检查数据库中是否存在相同类型的数据。如果已经存在数据意味着我想防止用户在数据库中输入重复数据. 在我的情况下,如果已经存在同一时间的预订,这就像预约,我想防止用户同时预订。我尝试使用查询功能,但它不能防止重复数据输入。有人请帮助我

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;
        
    

【问题讨论】:

现在您已经添加了代码 sn-p,我可以看到您正在比较 rdeptbotime。应该是rdept.equals(bodept) 是的,我改变了它,但它仍然无法正常工作。它将所有数据插入数据库而不检查条件@whenthemorningcomes 【参考方案1】:

从 Cloud Firestore 加载数据是异步进行的。当你从alreadyBooked返回时,数据还没有加载,onSuccess还没有运行,flag仍然是默认值。

查看这一点的最简单方法是使用一些日志语句:

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");

如果您运行此代码,它将打印:

开始监听

返回

从 Firestore 获取数据

这可能不是您期望的顺序。但它完美地解释了为什么在调用 alreadyBooked 时总是得到 false:数据根本没有及时从 Firestore 中返回。

解决这个问题的方法是改变您对问题的看法。您当前的代码具有逻辑:“首先检查它是否已经预订,然后添加一个新项目”。我们需要将其重新定义为:“开始检查它是​​否已被预订。一旦我们知道不是,添加一个新项目。”在代码中,这意味着所有需要 Firestore 数据的代码都必须在 onSuccess 内,或者必须从那里调用。

最简单的版本是将代码移入 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 的可重用性降低,因为现在它也包含插入新项目的代码。你可以通过定义自己的回调接口来解决这个问题:

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 实时数据库,适用相同的逻辑):

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中的主要内容,如果未能解决你的问题,请参考以下文章

检查 Flutter Firestore 中是不是已存在字段

Swift 5 Firestore:检查数据库中是不是存在集合

使用 React Hooks 和 Context 检查电子邮件是不是已经存在于 Firestore 的集合中

如何在更新期间检查该数据是不是已存在于数据库中(Mongoose And Express)

如何检查项目是不是存在于多个数组中

颤动检查云Firestore集合中是不是存在用户ID