【问题标题】: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

标签: android firebase google-cloud-firestore


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

【讨论】:

  • 非常感谢您的精彩解释。您提供了解决方案,也让我意识到我的代码有什么问题。非常感谢...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 2021-08-21
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
相关资源
最近更新 更多