Firebase - 通过 ID 列表获取元素
Firebase - get elements by list of IDs
我使用 firebase 作为我的数据库后端,并且有多对多的关系。
由于我的关系有点抽象,我将在这里使用一个简化的示例。假设我们有学生和讲座。学生可以听课,听课有听课学生名单。在整个应用程序中,这两个查询都需要,因此将列表保留在其中任何一个中都没有真正的优势。这个问题在像这样的 No-SQL 场景中似乎并不少见,我什至读过存储每个学生的所有讲座列表和每个讲座的学生列表,这是一个有效的解决方案。
假设我的 JSON 数据如下所示:
"students": {
"s1" : {
"name": "A",
"lectures": ["l1", "l2"]
},
"s2" : {
"name": "B",
"lectures": ["l2", "l3"]
}
}
和
"lectures": {
"l1" : {
"title": "lecture1",
"students": ["s1"]
},
"l2" : {
"title": "lecture2",
"students": ["s1", "s2"]
},
"l3" : {
"title": "lecture3",
"students": ["s2"]
}
}
其中 s1、s2、l1、l2、l3 是神秘的 Firebase ID。
使用这样的设置,很容易编写查询以获取学生 "s1" 的所有讲座作为数组 ["l1", "l2"].
但是,我无法弄清楚如何使用这组ID来获取相应的lecture元素,因为我只能查询一个ID。
我还想避免获取所有数据并在之后使用 Java-Code.
对其进行过滤
这样做就可以了:
Firebase ref = new Firebase("https://Whosebug.firebaseio.com/35963762");
ref.child("students/s1/lectures").addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot lessonKey: snapshot.getChildren()) {
ref.child("lectures").child(lessonKey.getValue(String.class)).addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot lectureSnapshot) {
System.out.println(lectureSnapshot.child("title").getValue());
}
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
public void onCancelled(FirebaseError firebaseError) {
}
});
输出:
lecture1
lecture2
关于您的数据结构的几点说明:
您正在嵌套不应该嵌套的数据结构。例如,此代码现在还加载它不需要的 lecture1 和 lecture2 的 students
列表。如果您将 "students in a lecture" 和 "lectures for a student" 移动到它们自己的顶级节点中,您将不会遇到此问题。
您将 "students in a lecture" 存储在一个数组中。这意味着如果你从数组中间删除一个讲座,你将不得不更新它后面的所有讲座。更常见的方法是将讲座 ID 存储为键,将虚拟 true
存储为值:
students_per_lecture: {
"l2" : {
"s1": true,
"s2": true
}
},
我使用 firebase 作为我的数据库后端,并且有多对多的关系。 由于我的关系有点抽象,我将在这里使用一个简化的示例。假设我们有学生和讲座。学生可以听课,听课有听课学生名单。在整个应用程序中,这两个查询都需要,因此将列表保留在其中任何一个中都没有真正的优势。这个问题在像这样的 No-SQL 场景中似乎并不少见,我什至读过存储每个学生的所有讲座列表和每个讲座的学生列表,这是一个有效的解决方案。 假设我的 JSON 数据如下所示:
"students": {
"s1" : {
"name": "A",
"lectures": ["l1", "l2"]
},
"s2" : {
"name": "B",
"lectures": ["l2", "l3"]
}
}
和
"lectures": {
"l1" : {
"title": "lecture1",
"students": ["s1"]
},
"l2" : {
"title": "lecture2",
"students": ["s1", "s2"]
},
"l3" : {
"title": "lecture3",
"students": ["s2"]
}
}
其中 s1、s2、l1、l2、l3 是神秘的 Firebase ID。 使用这样的设置,很容易编写查询以获取学生 "s1" 的所有讲座作为数组 ["l1", "l2"].
但是,我无法弄清楚如何使用这组ID来获取相应的lecture元素,因为我只能查询一个ID。 我还想避免获取所有数据并在之后使用 Java-Code.
对其进行过滤这样做就可以了:
Firebase ref = new Firebase("https://Whosebug.firebaseio.com/35963762");
ref.child("students/s1/lectures").addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot lessonKey: snapshot.getChildren()) {
ref.child("lectures").child(lessonKey.getValue(String.class)).addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot lectureSnapshot) {
System.out.println(lectureSnapshot.child("title").getValue());
}
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
public void onCancelled(FirebaseError firebaseError) {
}
});
输出:
lecture1
lecture2
关于您的数据结构的几点说明:
您正在嵌套不应该嵌套的数据结构。例如,此代码现在还加载它不需要的 lecture1 和 lecture2 的
students
列表。如果您将 "students in a lecture" 和 "lectures for a student" 移动到它们自己的顶级节点中,您将不会遇到此问题。您将 "students in a lecture" 存储在一个数组中。这意味着如果你从数组中间删除一个讲座,你将不得不更新它后面的所有讲座。更常见的方法是将讲座 ID 存储为键,将虚拟
true
存储为值:students_per_lecture: { "l2" : { "s1": true, "s2": true } },