无法使用Cloud Firestore写入多个位置

时间:2018-04-26 01:50:54

标签: java android firebase google-cloud-firestore

我想写一下Firebase中的两个位置:"民意调查"和"趋势"。

我已经成功完成了,但是我注意到我的第一次写作是将特定的"键"我添加并没有列出任何字段,而第二次写入确实显示了所有相关字段。为什么会这样,这被认为是最佳做法?我很惊讶自从我用两种不同的方法调用.add()后创建了相同的密钥。

            //write to Firebase Cloud Firestore
            mStoreBaseRef.collection("Polls").add(pollMap).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
                @Override
                public void onComplete(@NonNull Task<DocumentReference> task) {
                    if (task.isSuccessful()) {
                        DocumentReference docRef = task.getResult();
                        String key = docRef.getId();
                        Log.v("KEY", key);
                        Toast.makeText(getApplicationContext(), key, Toast.LENGTH_LONG).show();
                        CollectionReference pollAnswerRef = mStoreBaseRef.collection("Polls").document(key).collection("answers");
                        //TODO: need to add answers
                        for (int i = 0; i < mPollAnswers.size(); i++){
                            pollAnswerRef.document(String.valueOf(i + 1)).set((poll.answerConvert(mPollAnswers, i)), SetOptions.merge());
                        }
                    }
                }
            });

            //TODO: write to multiple locations in Firebase; check this location for epoch > 24 hours dated and delete with Cloud Functions
            mStoreBaseRef.collection("Trending").add(pollMap).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
                @Override
                public void onComplete(@NonNull Task<DocumentReference> task) {
                    if (task.isSuccessful()) {
                        DocumentReference docRef = task.getResult();
                        String key = docRef.getId();
                        Log.v("KEY", key);
                        Toast.makeText(getApplicationContext(), key, Toast.LENGTH_LONG).show();
                        CollectionReference pollAnswerRef = mStoreBaseRef.collection("Polls").document(key).collection("answers");
                        //TODO: need to add answers
                        for (int i = 0; i < mPollAnswers.size(); i++){
                            pollAnswerRef.document(String.valueOf(i + 1)).set((poll.answerConvert(mPollAnswers, i)), SetOptions.merge());
                        }
                    }
                }
            });

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为当您使用以下代码行时:

mStoreBaseRef.collection("Polls").add(pollMap).addOnCompleteListener(/* ... */)

您正在pollMap内写Polls集合,这是正确的。然后在onComplete()方法中使用以下代码行:

String key = docRef.getId();

这将返回将上述pollMap写入数据库时​​生成的确切ID。因此,将此键作为参数传递给以下代码行中的document()方法:

CollectionReference pollAnswerRef = mStoreBaseRef.collection("Polls").document(key).collection("answers");

表示您覆盖以下位置下的所有数据:

Firestore-root
    |
    --- Pools (collection)
          |
          --- d7kjSLqvM1qyS5t07Jxx (document)

因此,此位置下的所有内容都将被删除,并且会添加新数据。这种情况发生在Map的情况下,它将旧值替换为新值。如您的第一个屏幕截图所示,该位置下没有任何其他内容,但刚刚添加的新集合answers。要解决此问题,您需要使用update()方法而不是set()方法。

关于第二次写入,您要添加相同的pollMap,但这次是在Trending集合下,如第二个屏幕截图所示,一切正常,因为您不会使用其他写操作相同的参考再次使用以下代码行:

String key = docRef.getId();

生成一个新的id,并在以下代码行中使用它:

CollectionReference pollAnswerRef = mStoreBaseRef.collection("Polls").document(key).collection("answers");

最终将在与第一次写入相同的引用上创建新数据。看,您使用的是同一个集合Polls?这很可能是您在第一个集合中而不是在第二个集合中拥有更多文档的原因。

关于相同的id,我已经多次测试了与你的相同的代码或document()方法而没有传递任何参数,并且每次都生成了不同的id。我认为你以某种方式手动创建了具有该id的写操作。

总之,在代码中设置正确的引用,删除数据库中已有的数据并添加新数据,应该可以解决您的问题。