【问题标题】:Firestore not querying second collectionFirestore 不查询第二个集合
【发布时间】:2019-02-06 13:58:10
【问题描述】:

我是 android studio 和 firestore 数据库的新手 我在查询我的第二个 Firestore 集合时遇到了一些问题。正如标题所说,我正在查询两个集合,第一个是:

代码:

    firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
            .build();
    firestore.setFirestoreSettings(settings);
    firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {

            //<--------- Check if firestore entry is already downloaded into file --------->
            SingletonObjectivesId.getInstance().getIds().clear();
            for (QueryDocumentSnapshot document : task.getResult()) {
                Log.d(TAG, task.getResult().size() + " number of documents");
                SingletonObjectivesId.getInstance().setSize(task.getResult().size());

                if(document.exists() && document != null) { ...

第二个集合的格式如下:

用代码:

        firestore.collection("Routes")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {

                        Log.d(TAG, task.getResult().size() + " = task.getResult().size()");

                        for (QueryDocumentSnapshot document : task.getResult()) {
                            objectives_id.clear();
                            id_route = document.getId();

                            if(document.exists() && document != null) {
                                Map<String, Object> map = document.getData();
                                for (Map.Entry<String, Object> entry : map.entrySet()) {
                                    String field_name = entry.getKey() + "";
                                    String id = document.getString(field_name) + "";
                                    objectives_id.add(id);
                                }
                            }
                            routes.add(new Route(objectives, objectives_id, id_route));
                        }
                    } else {
                        Log.d(TAG, "Error getting documents: ", task.getException());
                    }
                }
            });

正如您在第二个代码中看到的,我添加了一个 Log.d(在 if (task.isSuccessful()) 之后),它将显示文档的数量。就我而言,第一个查询 Log.d 返回 3,第二个查询返回 0,尽管我有 2 个文档。我如何访问这 2 个文档?

谢谢。

【问题讨论】:

    标签: java android firebase google-cloud-firestore


    【解决方案1】:

    Firebase API 是异步的,这意味着 onComplete() 方法在被调用后会立即返回,并且它返回的 Task 的回调将在一段时间后被调用。无法保证需要多长时间。因此,数据可用可能需要几百毫秒到几秒钟的时间。由于该方法会立即返回,因此您尝试记录的文档数量尚未从回调中填充。

    基本上,您尝试从异步 API 同步使用值。这不是一个好主意。您应该按预期异步处理 API。

    一个快速解决这个问题的方法是将查询第二个集合的代码移到第一个回调中(在onComplete() 方法中)所谓的嵌套查询,否则我建议你从这个 post 我已经解释了如何使用自定义回调来完成。您也可以看看这个 video 以获得更好的理解。

    【讨论】:

    • 感谢您的快速解答。我将阅读您给我的链接,并尝试更好地了解 Firebase 的工作原理。再次感谢。
    • 嗨,我在观看视频后刚刚编辑了我的代码,但我仍然遇到同样的问题。至少现在查询是按正确的顺序进行的,但是第二个仍然没有项目,Log.d(TAG, task.getResult().size()) 仍然返回 0。
    • 我猜这可能与您调用方法的对象有关,但没有看到您的新代码,我帮不上什么忙。为此,我建议您使用自己的 MCVE 发布另一个新问题,以便我和其他 Firebase 开发人员可以帮助您。
    • 好的,我会这样做,但在那之前我注意到即使我的第一个集合也没有正确查询。我用另一个条目(文档)更新了它作为测试,似乎没有看到新条目。问题可能出在其他地方,而不是在我的代码中?
    • 让我们看看新问题与您更改的代码,看看那里发生了什么。
    【解决方案2】:

    按照视频中的步骤操作后,我更新了如下代码:

    我在课堂开始时创建了一个全局变量 firestore

    private FirebaseFirestore firestore;
    

    我有两个方法 readDataObjective 和 readDataRoute 以及两个接口 FirestoreCallback 和 FirestoreCallbackRoutes

    读取数据路由

        private void readDataRoute(FirestoreCallbackRoute firestoreCallbackRoute){
        firestore.collection("Trasee").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) { ...
    

    读取数据目标

       private void readDataObjective(FirestoreCallback firestoreCallback){
        firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {   
                    SingletonObjectivesId.getInstance().getIds().clear();
                    for (QueryDocumentSnapshot document : task.getResult()) { ...
    

    接口

    private interface FirestoreCallback{
        void onCallback(ArrayList<Objective> list);
    }
    
    private interface FirestoreCallbackRoute{
        void onCallback(ArrayList<Route> list);
    }
    

    在 onCreate 方法中,我像这样调用 readDataObjective 和 readDataRoute

    firestore = FirebaseFirestore.getInstance();
        FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder().build();
        firestore.setFirestoreSettings(settings);
    
        readDataObjective(new FirestoreCallback() {
            @Override
            public void onCallback(ArrayList<Objective> list) {
                for(Objective item : list){
                    //Create plainText Object - delimiter "/~/"
                    String data = "Title:" + item.getTitle() + "/~/" +
    
    ............................
    
         } else if(str.contains("Longitude:")){
                                obj.setLongitude(str.substring(10,str.length()));
                            }
    
                            start = crt + 2;
                        }
                    }
                    SingletonObjectivesArray.getInstance().getObjectives().add(obj);
                }
    
                readDataRoute(new FirestoreCallbackRoute() {
                    @Override
                    public void onCallback(ArrayList<Route> list) {
                        Log.d(TAG, 2 + " ");
                        ArrayList<Objective> routeObjectives = new ArrayList<>();
    
                        for (int i = 0; i < list.size(); i++) {
                            routeObjectives.clear();
                            for (int j = 0; j < SingletonObjectivesArray.getInstance().getObjectives().size(); j++){ ...
    

    提到 readDataRoute 在 readDataObjective 的最后被调用。

    我注意到问题不仅在于第二个查询,还在于第一个查询。我在第一个集合中添加了一个新文档,运行代码后,第一个查询返回旧数据(没有我的新条目)。

    【讨论】:

      猜你喜欢
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      相关资源
      最近更新 更多