Firebase Firestore搞乱阵列顺序

问题描述 投票:1回答:3

我正在使用Firebase的Firestore来存储我的iOS应用程序的数据。在Firestore中,我有两个集合。一个叫songs,一个叫playlistssongs集合包含许多文档,每个文档内部都有一个歌曲信息。这是songs文档的样子。

songs documet

然后,在我的收藏playlists它包含一些文件是播放列表。这是一个playlists文档的示例。

playlists document

我希望能够显示播放列表,然后从我的songs集合中获取该播放列表中的songTitles。所以,我做到了这一点:

var testPlaylistTitles = [String]()
db.collection("playlists").whereField("title", isEqualTo: "Test Playlist").getDocuments { (snapshot, error) in

       for document in (snapshot?.documents)! {
           self.testPlaylistTitles = ((document.data()["songTitles"] as? [String])!)

                }
          }

这使得变量testPlaylistTitles = ["Test Song", "Test Song 2", "Test Song 3"]。这太好了。但这是出错的地方。我想从我的songs系列中获取有关这些歌曲的信息。因此,我创建了一个for循环并循环播放歌曲以附加到我的其他艺术家,图像和标题阵列。就这个例子而言,我将使用returedTitles的变量。

var testPlaylistTitles = [String]()
db.collection("playlists").whereField("title", isEqualTo: "Test Playlist").getDocuments { (snapshot, error) in

       for document in (snapshot?.documents)! {
           testPlaylistTitles = ((document.data()["songTitles"] as? [String])!)

                }
       var returedTitles = [String]()
       for i in 0...testPlaylistTitles.count-1 {
       db.collection("songs").whereField("title", isEqualTo: testPlaylistTitles[i]).getDocuments(completion: { (snapshot, error) in
                    for document in (snapshot?.documents)! {
                        returedTitles.append((document.data()["title"] as? String)!)

                    }
                })
           } 
   }

现在,returedTitles等于原始testPlaylistTitles的洗牌版本。我一开始认为它不知何故是按字母顺序排序testPlaylistTitles,但事实并非如此。有没有人对正在发生的事情以及如何解决它有任何想法!非常感谢!这一直困扰着我。

swift firebase google-cloud-firestore
3个回答
1
投票

我不知道如何在swift中执行此操作,但我会将播放列表文档中歌曲的数据结构更改为歌曲为键的对象,然后在查询的第二个循环中将值更改为值,您使用键返回值,您应该能够按值排序。

{ 
  description: "test",
  songs: {
    "Test Song 1": 1,
    "Test Song 2": 3,
    "Test Song 4": 2
  },
  title: "Test playlist"
}

我还可以建议使用列表中歌曲的ID,因为您在以后的某个阶段检索数据。


0
投票

看起来你依赖于for循环中查询的执行顺序。请记住,getDocuments()是异步的,这意味着它会立即返回,并且结果会在一段时间后出现在回调中(无法保证需要多长时间)。因为它是异步的,所以你有效地同时开始查询testPlaylistTitles.count nubmer,每个查询都不考虑另一个。因此,您正在构建的数组将以未定义的顺序累积结果。为了帮助可视化,请在每个回调中放置一条日志消息,以查看它们实际调用的顺序。每次都包含数组的内容,以查看数组的构建方式。

如果结果的顺序很重要,您需要弄清楚自己的订单是什么。如果这意味着按顺序依次执行查询(这将是整体性能命中),那么您将必须以这种方式编码。

但最重要的是,你需要仔细考虑做异步工作。有关Firebase API异步原因的详细信息,请访问Please read this blog


0
投票

正如Doug指出的那样,问题是调用是异步的,因此它们不一定按照启动它们的顺序添加到数组中 - 它们在数据可用时添加。有几种方法可以解决这个问题,但是一个让你开始的建议是初始化你的数组,使它们的大小等于testPlaylistTitles的大小。然后,当您获得数据时,将其插入数组中的特定位置,而不是将其附加到数组的末尾。

var testPlaylistTitles = [String]()
db.collection("playlists").whereField("title", isEqualTo: "Test Playlist").getDocuments { (snapshot, error) in

   for document in (snapshot?.documents)! {
       testPlaylistTitles = ((document.data()["songTitles"] as? [String])!)

            }
   var returedTitles = [String](repeating: "title", count: testPlaylistTitles.count)
   for i in 0...testPlaylistTitles.count-1 {
       db.collection("songs").whereField("title", isEqualTo: testPlaylistTitles[i]).getDocuments(completion: { (snapshot, error) in
            if (snapshot!.documents.count) > 0 {
                    let doc = (snapshot?.documents.first)!
                    returedTitles[i] = ((doc.data()["title"] as? String)!)

                }
            })
       } 
}

在这段代码中,我初始化了一个testPlaylistTitles大小的数组。每个索引的值只是“标题”开头,但是一旦下载,就会被Firestore中的值替换。

© www.soinside.com 2019 - 2024. All rights reserved.