Как структурировать список поиска в Firestore? - PullRequest
0 голосов
/ 05 января 2019

Я хочу показать список исполнителей в моем приложении, которые пользователь сможет искать. Однако я не уверен, как сохранить это в Firestore?

Сначала я создал коллекцию «searchLists» с документом для каждого диджея, но это означает, что партия документов прочитана, поэтому об этом не может быть и речи.

Теперь я создал документ под названием «Artist», в котором есть поле «ArtistDictionary», в котором содержатся все художники.

| 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 - это структура, содержащая поле «name».)

И я имею в виду, что это работает, но я все еще новичок в Firestore, и это вроде как не так. Это? Или это то, как я должен / мог бы это сделать?

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Во-первых, ответ Алекса на 100% правильный.

Я хочу добавить несколько дополнительных точек данных, которые могут помочь вам в долгосрочной перспективе.

Первый элемент - массивы. Массивы очень сложны в базах данных NoSQL - хотя они предоставляют данные логической последовательности через индекс, 0, 1, 2 они не ведут себя как массив в коде - так, например; Предположим, вы хотите вставить элемент в индекс. Ну, вы не можете (* вы можете, но это не просто вызов 'insert'). Кроме того, вы не можете нацеливать элементы массива в запросах, что ограничивает их полезность. Наименьшей единицей изменения в поле массива Firestore является все поле - меньшие изменения в отдельных элементах поля не могут быть внесены. Исправление состоит в том, чтобы не использовать массивы и позволить FireStore создавать идентификаторы документов для ваших «объектов» данных на лету, например. «ключи» к узлу

Вторая проблема - (которая может не быть проблемой в настоящее время) - как обрабатываются данные. Предположим, что вы выпустили свое приложение, и у пользователя есть 2 миллиона художников в их коллекции - с вашим кодом, как есть, все эти данные загружаются за один раз, что, вероятно, будет не лучшим интерфейсом, но, кроме того, это может привести к переполнению памяти устройство. Поэтому работать с «кусками» данных намного проще как на устройстве, так и на пользователе.

Итак, я собрал пример кода, чтобы помочь с этим.

Первый класс для хранения данных об исполнителе. Просто отслеживайте идентификатор документа и имя исполнителя.

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)

Да, и вы заметите, что теперь функция сортировки идет по серверу, а не по устройству - поэтому, если есть миллион исполнителей, она сортируется на сервере перед доставкой на устройство, что будет значительно быстрее.

Вы также можете легче выполнять запросы для определенных данных об исполнителе, и вам не нужно заботиться о хранении, поскольку каждый исполнитель является собственным документом вместо всех исполнителей в одном.

Надеюсь, это поможет!

0 голосов
/ 05 января 2019

Сначала я создал коллекцию "searchLists" с документом для каждого диджея, но это означает, что многие документы читаются, поэтому об этом не может быть и речи.

Это правильный подход, поэтому вы должны продолжать его.

Почему я так говорю?

Согласно официальной документации относительно данных моделирования в базе данных Cloud Firestore:

Cloud Firestore оптимизирован для хранения больших коллекций небольших документов.

Хранение данных в массиве - неплохой вариант, но он, скорее всего, используется, скажем, для хранения favorite djs. Я говорю это, потому что документы имеют ограничения в Firestore. Таким образом, существуют некоторые ограничения в отношении объема данных, которые вы можете поместить в документ. В соответствии с официальной документацией относительно использования и ограничений :

Максимальный размер документа: 1 МБ (1 048 576 байт)

Как видите, вы ограничены 1 МБ данных в одном документе. Когда мы говорим о сохранении текста, вы можете хранить его в значительной степени, но по мере увеличения массива будьте осторожны с этим ограничением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...