如何删除Firestore词典值?

时间:2019-05-31 09:22:24

标签: swift firebase dictionary google-cloud-firestore

我在这样设置的文档中有一个值:

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_ $长度]:无法识别   选择器发送到实例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 :(得分:0)

似乎没有办法用字典来做到这一点,只有一个数组。因此,我不得不删除整个部分,然后像这样重建它:

 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]
}

答案 1 :(得分:0)

我知道您回答了自己的问题,但我想建议可能有一个更优雅的解决方案。

问题中缺少一些数据点,因此我将举一个示例案例-这可能在整个思考过程中有用。

让我们假设您的应用允许专利(用户)跟踪处方。这意味着将有多个用户,每个用户都有一个处方。那个处方有药物和剂量。

当用户想要删除处方时,代码将全部加载并迭代,直到找到正确的处方,然后将其删除。这就需要遍历真正效率低下的数据。

让我们提出另一种方法,我们假定这是针对用户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
        }

    }
}

值得注意的是,此函数为每个处方创建一个唯一的子节点并捕获对其的引用(这是piquot_0和discription_1 id的来源)。

该引用将具有一个documentID。这将使每个用户都有无限数量的独特处方。

然后,处方信息可以显示在UI中的tableView中。 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()
}