Как удалить значение словаря Firestore? - PullRequest
2 голосов
/ 31 мая 2019

У меня есть значение в документе, которое я установил следующим образом:

func uploadMedDosage(dosage: String, medication: String) {
    let docRef = db.collection("users").document(userId!)
    let updateData = ["medications" : [medication : dosage]]

    docRef.setData(updateData, merge: true) { (err) in
        if err != nil {
            print(err?.localizedDescription as Any)
            self.view.makeToast(err?.localizedDescription as! String)
        } else {
            self.refresh()
            print(" Data Uploaded")
        }
    }
}

Теперь мне нужно удалить это значение, но я не могу понять, как:

func removeMedDosage(dosage: String, medication: String) {
    let docRef = db.collection("users").document(userId!)
    let data = [[medication : dosage] : FieldValue.delete()]

    docRef.updateData(["medications" : data]) { (err) in
        print("delete")
    }
}

Это компилируется, но вызывает сбой:

Завершение приложения из-за необработанного исключения «NSInvalidArgumentException», причина: '- [_ TtGCs26_SwiftDeferredNSDictionarySSSS_ $ length]: нераспознанный селектор, отправленный в экземпляр 0x2830ca100'

Я пробовал много разных вариантов, включая

 let data = [[medication : dosage]]

    docRef.updateData(["medications" : FieldValue.arrayRemove(data)]) { (err) in
        print("delete")
    }

Данные в Firestore установлены так:

medications {
   Venlafaxine : 37.5,
   Sertraline : 100
}

Как я могу удалить строку [Venlafaxine: 37.5] по существу.

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Я знаю, что вы ответили на свой вопрос, но я хотел предположить, что может быть более элегантное решение.

В этом вопросе отсутствуют некоторые данные, поэтому я приведу пример случая - это можетбыть полезным в общем процессе мышления.

Предположим, что ваше приложение позволяет патентам (пользователям) отслеживать их рецепты.Это означает, что будет несколько пользователей, каждый из которых имеет рецепт.Этот рецепт имеет лекарство и дозировку.

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

Давайте предложим другой метод, и мы предположим, что это для пользователя 0 (uid_0)

Вот как будет выглядеть структура Firestore

user_prescriptions
    uid_0
       prescriptions
          prescription_0
             medication: "some med"
             dosage: "some dosage"
          prescription_1
             medication: "some med"
             dosage: "some dosage"  
     uid_1
        prescriptions
          prescription_0
             medication: "some med"
             dosage: "some dosage"
          prescription_1
             medication: "some med"
             dosage: "some dosage"  

когда пользователь хочет добавить лекарство, мы вызываем функцию uploadPrescription и передаем ему лекарство и дозировку

self.uploadPrescription(dosage: "100mg", medication: "Aspirin")

и вот функция для записи этогоданные в Firestore.

func uploadPrescription(dosage: String, medication: String) {
    let uid = "uid_0"
    let collectionRef = db.collection("users_prescriptions").document(uid).collection("prescriptions")
    let prescriptionData = ["medication": medication,
                            "dosage": dosage]
    var ref: DocumentReference? = nil
    ref = collectionRef.addDocument(data: prescriptionData) { err in
        if let err = err {
            print(err.localizedDescription)
            return
        } else {
            let docJustAddedRef = ref?.documentID
            print(docJustAddedRef!)
            //maybe create a PrescriptionClass and add it to a tableview
        }

    }
}

Интересно отметить, что эта функция создает уникальный дочерний узел для каждого рецепта и захватывает ссылку на него (откуда берутся идентификаторы prescription_0 и prescription_1).

Эта ссылка будет иметь идентификатор документа.Это позволит каждому пользователю иметь бесконечное количество уникальных рецептов.

Тогда информация о рецептах может отображаться в пользовательском интерфейсе, возможно, в виде таблицы.DocumentID является идентификатором этого конкретного рецепта и с тех пор будет использоваться для удаления или изменения информации о рецепте.Много раз при запуске приложения все предписания будут загружаться в класс, и каждое из них будет храниться в массиве, используемом в качестве источника данных tableView.Когда пользователь проведет пальцем по удалению, вы получите строку, которую он хочет удалить, получите этот объект предписания из массива - удалите его из массива, а затем, используя documentID, удалите его из Firestore.

func removeMedDosage(documentID: String) {
    let uid = "uid_0"
    let docRef = db.collection("users_scripts").document(uid).collection("prescriptions").document(documentID)
    docRef.delete()
}
0 голосов
/ 31 мая 2019

Кажется, нет способа сделать это с помощью словаря, только массив.Поэтому мне пришлось удалить весь раздел и перестроить его следующим образом:

 func removeMedDosage(dosage: String, medication: String) {
    print("remove")
    let docRef = db.collection("users").document(userId!)

    removeDictionary = [:]

    for (index, element) in self.meds.enumerated() {
        removeDictionary[element] = self.dosages[index]
    }

    let data = removeDictionary

    docRef.updateData(["medications" : data]) { (err) in

    }
    self.refresh()
}

При этом я удалил выбранный из массивов, используемых для tableView:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let delete = UITableViewRowAction(style: .destructive, title: "delete") { (action, indexPath) in

        let index = indexPath.row
        let med = self.meds[index]
        let dose = self.dosages[index]

        self.meds.remove(at: index)
        self.dosages.remove(at: index)

        self.tableView.deleteRows(at: [indexPath], with: .fade)
        self.removeMedDosage(dosage: dose, medication: med)

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