如何从Firestore获取数组?

时间:2018-05-08 12:09:54

标签: java android firebase google-cloud-firestore

enter image description here

我将上述数据结构存储在Cloud Firestore中。我想保存dungeon_group,这是存储在Firestore中的字符串数组。

我很难获取数据并存储为数组。我只能得到一个奇怪的字符串,但任何方法存储为字符串数组?以下是我使用的代码。

我能够在Swift中实现这一目标,但不知道如何在Android中做同样的事情。

//夫特

Firestore.firestore().collection("dungeon").document("room_en").getDocument { (document, error) in
        if let document = document {
            let group_array = document["dungeon_group"] as? Array ?? [""]
            print(group_array)
        }

    }

// JAVA Android

    FirebaseFirestore.getInstance().collection("dungeon").document("room_en").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                DocumentSnapshot document = task.getResult();
                String group_string= document.getData().toString();
                String[] group_array = ????

                Log.d("myTag", group_string);
            }
        });

控制台OutPut如下:{dungeon_group = [3P,紧急,任务挑战,降级,协作,每日,技术,正常]}

4 个答案:

答案 0 :(得分:4)

当您致电DocumentSnapshot.getData()时,它会返回一张地图。您只是在该地图上调用toString(),这将转移文档中的所有数据,这并不是特别有帮助。您需要按名称访问dungeon_group字段:

DocumentSnapshot document = task.getResult();
List<String> group = (List<String>) document.get("dungeon_group");
  • 编辑: 类型转换中的语法错误

答案 1 :(得分:4)

如果你想获得整个dungeon_group数组,你需要像这样迭代Map

Map<String, Object> map = documentSnapshot.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
    if (entry.getKey().equals("dungeon_group")) {
        Log.d("TAG", entry.getValue().toString());
    }
}

但请注意,即使dungeon_group对象作为数组存储在数据库中,entry.getValue()也会返回ArrayList不是数组。

如果您考虑使用这种替代数据库结构,那么更好的方法就是使用group中的每个Map,并将所有值设置为布尔true

dungeon_group: {
    3P: true,
    Urgent: true,
    Mission Chalange: true
    //and so on
}

使用此结构,您还可以根据dungeon_group地图中存在的属性进行查询,否则可以在official documentation中查询:

  

虽然Cloud Firestore可以存储数组, it does not support 查询数组成员或更新单个数组元素。

编辑2018年8月13日:

根据有关array membership的更新文档,现在可以使用whereArrayContains()方法根据数组值过滤数据。一个简单的例子是:

CollectionReference citiesRef = db.collection("cities");
citiesRef.whereArrayContains("regions", "west_coast");
  

此查询返回每个城市文档,其中regions字段是包含west_coast的数组。如果数组具有您查询的值的多个实例,则文档仅包含在结果中一次。

答案 2 :(得分:2)

您的问题有两种解决方案,一种是您可以通过下一种方式从文档中转换值:

DocumentSnapshot document = task.getResult();
List<String> dungeonGroup = (List<String) document.get("dungeon_group");

或者,我会向您推荐此解决方案,因为在您开发应用时,您的模型总是有可能发生变化。这个解决方案只是模拟Firebase POJO中的所有内容,即使它们只有一个参数:

public class Dungeon {

    @PropertyName("dungeon_group")
    private List<String> dungeonGroup;

    public Dungeon() {
        // Must have a public no-argument constructor
    }

    // Initialize all fields of a dungeon
    public Dungeon(List<String> dungeonGroup) {
        this.dungeonGroup = dungeonGroup;
    }

    @PropertyName("dungeon_group")
    public List<String> getDungeonGroup() {
        return dungeonGroup;
    }

    @PropertyName("dungeon_group")
    public void setDungeonGroup(List<String> dungeonGroup) {
        this.dungeonGroup = dungeonGroup;
    }
}

请记住,您可以使用Annotation @PropertyName来避免以与数据库中的值相同的方式调用变量。 最后你可以这样做:

DocumentSnapshot document = task.getResult();
Dungeon dungeon= toObject(Dungeon.class);

希望它会对你有所帮助! 快乐的编码!

答案 3 :(得分:1)

由于将文档转换为字符串时,您的文档看起来像这样"dongeon_group=[SP, urgent, missinon challenge,...],因此请通过String.valueOf(document.getData())

我认为另一种简单实现此目的的方法是将文档立即解压缩为一个数组字符串,如下所示:

String[] unpackedDoc = document.getData().entrySet().toArray()[0].toString().split("=")[1].split(",");

说明

document是从documentSnapshot.getDocuments()获得的,它返回包含您的文档的列表。

由于您的文档似乎是从Firestore嵌套的,因此调用document.getData()将返回列表,该列表当然是文档的单个元素。 document.getData().entrySet()将使文档准备好转换为还包含单个元素的数组(单独使用getData()不能做到这一点)。 访问单个元素document.getData().entrySet().toArray()[0],然后将其转换为字符串,document.getData().entrySet().toArray()[0].toString()将留下一个字符串,您可以将其拆分(使用字符串中的=),然后进行第二部分。 第二部分也可以拆分为包含文档值的数组。

由于此解决方案一次只能转换一个元素,因此可以将其包装在循环中,以便可以转换所有可用的文档。

例如:

for(DocumentSnapshot document :documentSnapshot.getDocuments()){ String[] unpackedDoc = document.getData().entrySet().toArray()[0].toString().split("=")[1].split(","); //do something with the unpacked doc

}