[英]How to get an array from Firestore?
我将如下所示的数据结构存储在 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安卓:
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);
}
});
控制台输出如下:
{dungeon_group=[3P,紧急,任务挑战,降临,协作,日常,技术,普通]}
当您调用DocumentSnapshot.getData() 时,它会返回一个 Map。 您只是在该地图上调用 toString() ,这将为您提供文档中所有数据的转储,这并不是特别有用。 您需要按名称访问dungeon_group
字段:
DocumentSnapshot document = task.getResult();
List<String> group = (List<String>) document.get("dungeon_group");
您的问题有两种解决方案,一种是您可以通过以下方式从文档中转换值:
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);
希望它会帮助你! 快乐编码!
如果你想获得整个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
地图中存在的属性查询它,否则如官方文档中所示:
虽然 Cloud Firestore 可以存储数组,
it does not support
查询数组成员或更新单个数组元素。
2021 年 1 月 13 日编辑:
如果您有一个对象数组而不是字符串值数组,那么您可以将该对象数组映射到自定义对象列表,如以下文章中所述:
2018 年 8 月 13 日编辑:
根据有关数组成员资格的更新文档,现在可以使用whereArrayContains()
方法基于数组值过滤数据。 一个简单的例子是:
CollectionReference citiesRef = db.collection("cities");
citiesRef.whereArrayContains("regions", "west_coast");
此查询返回每个城市文档,其中区域字段是包含 west_coast 的数组。 如果数组具有您查询的值的多个实例,则该文档仅包含在结果中一次。
由于您的文档看起来像这样"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
}
我如何在我的生产应用程序中存档。
全球申报
private final FirebaseFirestore FIRE_STORE_DB;
参考
this.FIRE_STORE_DB = FirebaseFirestore.getInstance();
征收方式
public CollectionReference getCOLLECTION_REF() {
return FIRE_STORE_DB.collection(Global.COLLECTION_USER);
}
如果等于返回false,我的recuirment是获取数组的最后一个索引时间到当前时间。
public void dailyCheck(String UID, OnCheckIn onCheckIn) {
getCOLLECTION_REF().document(UID).get().addOnSuccessListener(documentSnapshot -> {
if (documentSnapshot.exists()) {
List< String > dateList = (List< String >) documentSnapshot.get(FIELD_DAILY_CHECK_IN);
if (dateList != null) {
String lastDate = dateList.get(dateList.size() - 1);
if (!lastDate.equals(getCurrentTimeStamp())) {
onCheckIn.todayCheckIn(false);
} else {
Log.e(TAG, "LAST DATE EQUAL ---------------> RETURN");
onCheckIn.todayCheckIn(true);
}
} else {
Log.e(TAG, "DATE LIST ---------------> NULL RETURN");
}
} else {
Log.e(TAG, "LOGIN DATE NOT EXIST ---------------> checkInDate");
}
});
}
我如何在我的活动中获得它
public interface OnCheckIn {
void todayCheckIn(boolean check);
}
下面 - 我怎么称呼它
dbHelper.dailyCheck(CURRENT_USER, check -> {
if (!check) {
// todo
} else {
//
}
});
注释 - 这个 dbHelper 是一个类名->如果你对这个答案有任何疑问,请在下面评论
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.