我想在Cloud Firestore中定义这两个集合。一些示例数据如下所示:
播放列表:
歌曲:
playlistId:“ playlist1”
标题:“ song2”
playlistId:“ playlist1”
标题:“ song3”
此外,在我的Android应用中,我想显示所有播放列表和所有歌曲的单独列表。但是,在显示所有播放列表的列表时,我想根据“ songCount”中的值显示每个播放列表的名称以及每个播放列表中包含的歌曲数。
请告知我需要在Cloud Firestore中进行哪种查询才能实现此目标。是否有可用的Join函数,或者我是否必须将Songs集合放入循环并将具有playlistId的歌曲计数为“ playlist1”,然后对要在播放列表列表中显示的所有播放列表重复此操作?我想有一个更智能的解决方案,但在互联网上找不到。
任何帮助都将是一个很大的帮助。感谢您的宝贵时间。
答案 0 :(得分:2)
是否可以使用Join功能?
不幸的是,Firestore中没有联接查询。 Firestore中的查询很浅:它们仅从运行查询的集合中获取项目。无法通过单个查询从顶级集合以及其他集合或子集合中获取文档。 Firestore不一次性支持跨不同集合的查询。单个查询只能使用单个集合中的文档属性。因此,我能想到的最简单的解决方案是使用类似于以下内容的数据库结构:
Firestore-root
|
--- playlists (collection)
| |
| --- playListId (document) //The unique id of the play list
| |
| --- name: "playlist1"
|
--- songs (collection)
|
--- playListId (document) //The same as the above playListId
|
--- playListSongs
|
--- songId
|
--- title: "song1"
要显示所有播放列表,只需在playlists
引用上附加一个侦听器并获取所有playlist
对象。如果要获取与特定播放列表对应的所有歌曲,只需在songs\playListId\playListSongs
上附加一个侦听器,然后获取所有song
个对象。
关于与播放列表相对应的所有Sog的计数,我建议您从此 post 中查看答案,在此我解释了可以实现的目标。因此,根据我回答的最后一部分,您的Firebase实时数据库结构应如下所示:
Firebase-realtime-database-root
|
--- playlists
|
--- playListIdOne: numberOfSongs
|
--- playListIdTwo: numberOfSongs
编辑:
我不能说我已经完全理解它,尤其是因为第一个答案涉及FireStore,第二个答案涉及Firebase实时数据库。
我为您提供了此解决方案,因为如果您想每次添加或删除歌曲时都使用Cloud Firestore计数和更新元素,则Firestore将对每次写入/删除操作收取费用。 Firebase实时数据库还有另一个pricing plan,因此您无需为此付费。请参见Firestore pricing,直到结尾,请重读。我从此 post 中得到的答案。
而且,我真的无法获得计算歌曲数的过程。
这是从Firestore获取编号歌曲并将其写入Firebase实时数据库的方法:
rootRef.collection("songs").document(playListId).collection("playListSongs")
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
Log.d("TAG", task.getResult().size() + "");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference playListIdRef = rootRef.child("playlists").child(playListId);
playListIdRef.setValue(task.getResult().size());
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
这是您可以阅读的方式:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference playListIdRef = rootRef.child("playlists").child(playListId);
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
long playListIdOne = dataSnapshot.getValue(String.Long);
Log.d(TAG, "playListIdOne: " + playListIdOne);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
playListIdRef.addListenerForSingleValueEvent(valueEventListener);
第二,根据您建议的结构,我如何获得所有播放列表中所有歌曲的列表?
在这种情况下,您应该创建另一个名为allSongs
的集合。数据库中的附加集合应如下所示:
Firestore-root
|
--- allSongs
|
--- songId
|
--- //song details
这种做法称为denormalization
,是Firebase的常见做法。为了更好的理解,我建议您观看此视频Denormalization is normal with the Firebase Database。它用于Firebase实时数据库,但相同的规则适用于Cloud Firestore。
此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。
请记住,同一首歌曲可以在多个播放列表中找到。
没关系,因为每个子代都有不同的ID。