如何在Firestore中构建搜索列表?

时间:2019-01-05 03:25:19

标签: ios swift firebase google-cloud-firestore

我想在我的应用程序中显示一个艺术家列表,用户可以通过它进行搜索。但是我不确定如何将其保存在Firestore中吗?

首先,我为每个DJ创建了一个带有文档的“ searchLists”集合,但这意味着文档的很多读取,所以这是不可能的。

现在,我创建了一个名为“艺术家”的文档,其中包含“ artistsDictionary”字段,其中包含所有艺术家。

| searchLists (collection)
   * artists (document)
      - artistsArray (array)
          0: (map)
            name: "Artist 0" (string)
          1: (map)
            name: "Artist 1" (string)
          2: (map)
            name: "Artist 2" (string)

然后我按照以下方式检索并解析数组:

let docRef = db.collection("searchLists").document("artists")
docRef.getDocument { (document, error) in
    if let document = document, document.exists {
        guard let documentData = document.data() else { return }
        let artistsDictionaryArray = documentData["artistsArray"] as? [[String: Any]] ?? []
        let parsedArtists = artistsDictionaryArray.compactMap {
            return SimpleArtist(dictionary: $0)
        }
        self.artistsArray = parsedArtists
    } else {
        print("Document does not exist")
    }
}

(SimpleArtist是包含“名称”字段的结构。)

我的意思是,它可以工作,但是我还是Firestore的新手,这似乎还不错。是吗?还是这是我应该/应该如何做?

2 个答案:

答案 0 :(得分:2)

  

首先,我为每个DJ创建了一个带有文档的“ searchLists”集合,但这意味着要读取大量文档,所以这是不可能的。

这是正确的方法,因此您应该继续进行下去。

  

我为什么这么说?

根据Cloud Firestore数据库中有关modeling data的官方文档:

  

Cloud Firestore经过优化,可以存储大量小文件。

将数据存储在数组中并不是一个坏选择,但这很有可能被使用,例如存储favorite djs。我之所以这样说是因为文档在Firestore中有限制。因此,在文档中可以放入多少数据方面存在一些限制。根据有关usage and limits的官方文档:

  

文档的最大大小:1 MiB(1,048,576字节)

如您所见,单个文档中的数据总数限制为1 MiB。当我们谈论存储文本时,您可以存储很多,但是随着数组变大,请注意此限制。

答案 1 :(得分:2)

首先,亚历克斯的答案是100%正确的。

我想添加一些其他数据点,从长远来看可能对您有帮助。

第一项是数组。数组在NoSQL数据库中非常具有挑战性-尽管它们通过索引0、1、2提供逻辑序列数据,但它们的行为并不像代码中的数组一样。假设您想在索引处插入一个项目。好吧-您不能(*您可以,但这不只是一个简单的“插入”调用)。另外,您不能在查询中定位数组元素,这限制了它们的用途。 Firestore数组字段中最小的更改单位是整个字段-无法对字段的各个元素进行较小的更改。解决方法是不使用数组,而是让FireStore即时为您的数据``对象''创建documentID。节点的“键”

第二个问题-(当前可能不是问题)是如何处理数据的。假设您发布了应用程序,并且用户中有200万艺术家,那么按原样使用您的代码,一次下载所有这些数据可能不是最佳的UI体验,但是它可能会淹没用户的记忆。设备。因此,在设备和用户上处理数据的“块”变得容易得多。

所以我整理了一些示例代码来帮助解决这个问题。

首先是一个用于存储艺术家数据的类。只需跟踪documentID和艺术家名称即可。

class ArtistClass {
    var docId = ""
    var name = ""

    init(aDocId: String, aName: String) {
        self.docId = aDocId
        self.name = aName
    }
}

和一个用于保留艺术家的类数组。这可能是tableView的潜在数据源。

var artistArray = [ArtistClass]()

这是将艺术家作为文档而不是数组编写。 documentID是为每个艺术家创建的FireStore生成的“密钥”。

func writeArtists() {
    let artistsRef = self.db.collection("artists")

    let floyd = [
        "name": "Pink Floyd"
    ]
    let zep = [
        "name": "Led Zeppelin"
    ]
    let who = [
        "name": "The Who"
    ]

    artistsRef.addDocument(data: floyd)
    artistsRef.addDocument(data: zep)
    artistsRef.addDocument(data: who)
}

,然后读取所有所有艺术家的音乐。

func readArtists() {
    let artistsRef = self.db.collection("artists")

    artistsRef.getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                let docId = document.documentID
                let name = document.get("name") as! String
                let artist = ArtistClass(aDocId: docId, aName: name)
                self.artistArray.append(artist)
            }

            for a in self.artistArray { //prints the artists to console
                print(a.docId, a.name)
            }
        }
    }
}

所以您在Firestore中的数据看起来像这样

artists (collection)
   8lok0a0ksodPSSKS
      name: "Let Zeppelin"
   WKkookokopkdokas
      name: "The Who"
   uh99jkjekkkokoks
      name: "Pink Floyd"

那么酷的部分。假设您有一个tableView可以一次显示10位艺术家,并带有向下按钮以查看接下来的10位艺术家。

let artistsRef = self.db.collection("artists").order(by: "name").limit(to: 10)

哦-您会注意到排序功能现在是服务器而不是设备-因此,如果有一百万个艺术家,则会在服务器上对它进行排序,然后再将其交付给设备,

>

然后,您还可以更轻松地对特定艺术家数据执行查询,而不必担心存储问题,因为每个艺术家都是他们自己的文档,而不是所有艺术家都在同一文档中。

希望有帮助!