Firebase会为同一查询返回不同的结果。的iOS

时间:2016-11-29 08:30:57

标签: ios firebase firebase-realtime-database

我通过电子邮件和密码输入时有部门结构,我通过电子邮件寻找部门的模型,但遇到错误,相同数据的结果可能不同。例如,如果是第一种方法,则查询返回模型,以下查询可以返回NSNull

部门的数据结构。

{
  "departments" : {
    "19537648-B6DA-4F63-9AFF-EFC4754630D6" : {
      "createdAt" : "502100506.440385",
      "email" : "dev@test.com",
      "isCertified" : false,
      "isMain" : false,
      "mainVendorID" : "YeLf8kzE1LfWwHnWwLJTWsaPinI3",
      "title" : "",
      "uid" : "19537648-B6DA-4F63-9AFF-EFC4754630D6"
    },
    "4552E741-B9B6-4733-84C1-7DE7FFC0FD4B" : {
      "createdAt" : "502100536.218835",
      "email" : "department@test.com",
      "isCertified" : false,
      "isMain" : false,
      "mainVendorID" : "YeLf8kzE1LfWwHnWwLJTWsaPinI3",
      "title" : "",
      "uid" : "4552E741-B9B6-4733-84C1-7DE7FFC0FD4B"
    },
    "DBEFBF16-71FE-4AB6-BEA6-5BF042D1AB1D" : {
      "createdAt" : "502100521.083035",
      "email" : "tester@test.com",
      "isCertified" : false,
      "isMain" : false,
      "mainVendorID" : "YeLf8kzE1LfWwHnWwLJTWsaPinI3",
      "title" : "",
      "uid" : "DBEFBF16-71FE-4AB6-BEA6-5BF042D1AB1D"
    }
  }

我的要求

let ref = FIRDatabase.database().reference()
          .child(FirebaseDatabaseManager.DatabaseMainGateways.departments.rawValue)
          .queryOrdered(byChild: "email").queryEqual(toValue: departmentEmail)

ref.observeSingleEvent(of: .value, with: { (snapshot) in
    if snapshot.value is NSNull {
        debugPrint(“value is NSNull”)
        notExist?()
    } else {

    }
}, withCancel: { (error) in

})

可能是什么问题以及如何解决?谢谢!

更新

Firebase规则

{
  "rules": {
    ".read": true,
    ".write": "auth != null",

    "departments": {
      ".indexOn": "email"
    },

  }
}

更新1

任务接下来,有必要确保当我们向主要供应商(可以使用Google +或电子邮件登录的普通Firebase用户)向用户创建自己的部门(具有特殊限制的用户)时数据)。如果我们已经拥有一个帐户,Firebase不允许在系统中注册新用户,但必须由主供应商将用户名和密码传递给他的部门。所以我的做法不一样。在创建新部门时(通过电子邮件),我首先检查已经在主要供应商列表中创建另一个部门的电子邮件是否已添加。

func addDepartment(departmentModel: RealmVendor, success: (() -> Void)?, isCreated: (() -> ())?, fail: ((_ error: Error) -> ())?) {
    guard let currentVendor = RealmManager.shared.getCurrentVendor(isMain: true) else { return }

    let checkingQuery = FIRDatabase.database().reference().child(FirebaseDatabaseManager.DatabaseMainGateways.vendors.rawValue).child(currentVendor.uid).child(DatabaseMainVendorGateways.departmentsEmails.rawValue).queryEqual(toValue: departmentModel.email).queryOrderedByValue()

    queries.append(checkingQuery)

    checkingQuery.observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.value is NSNull {
            // creating a new department
            debugPrint("Create a new department")
            self.createDepartment(departmentModel: departmentModel, success: {
                success?()
            }, fail: { (error) in
                fail?(error)
            })
        } else {
            // department was created
            debugPrint("department was created")
            isCreated?()
        }
    }) { (error) in
        debugPrint("error", error)
        fail?(error)
    }
}

下一步,如果部门不是通过此电子邮件创建的,那么我将电子邮件添加到主要供应商的模型列表中

private func createDepartment(departmentModel: RealmVendor, success: (() -> Void)?, fail: ((_ error: Error) -> ())?) {
    guard let currentVendor = RealmManager.shared.getCurrentVendor(isMain: true) else { return }
    let ref = FIRDatabase.database().reference().child(FirebaseDatabaseManager.DatabaseMainGateways.vendors.rawValue).child(currentVendor.uid).child("departmentsEmails").childByAutoId()
    ref.keepSynced(true)

    references.append(ref)

    ref.setValue(departmentModel.email) { (error, ref) in
        if error == nil {
            // save department to realm that we can show all departments in department list in app
            debugPrint("save department to realm", departmentModel.uid)

            RealmManager.shared.saveVendor(departmentModel)

            self.createFirstDepartmentModel(departmetnModel: departmentModel)
            success?()
        } else {
            fail?(error!)
        }
    }
}

然后我调用该函数来创建Department的第一个模型。

private func createFirstDepartmentModel(departmentModel: RealmVendor) {
    FirebaseDatabaseDepartmentManager.shared.savePreservationDepartmentOnServer(departmentModel)
}


func savePreservationDepartmentOnServer(_ realmDepartment: RealmVendor) {
    let refDatabase = FIRDatabase.database().reference().child(FirebaseDatabaseManager.DatabaseMainGateways.vendorDepartments.rawValue).child(realmDepartment.mainVendorUID!).child(realmDepartment.uid)

    references.append(refDatabase)

    refDatabase.observeSingleEvent(of: .value, with: { (snapshot) in
        if let _ = snapshot.value as? [String : Any] {
            // already existed. save the updated model, since the seller has already registered with the server, and not to spoil its current data
        } else {
            refDatabase.keepSynced(true)
            // it isn't existed.  save a new model, as the seller is not registered on the server
            let userInfoDict = realmDepartment.toJSON()

            refDatabase.setValue(userInfoDict) { (error, ref) in
                if error == nil {
                    self.createPath(realmDepartment)
                } else {
                    debugPrint(error!.localizedDescription)
                }
            }
        }
    })
}

然后,创建路径模型,为了注册用户帐户部门,他能够找到数据库中模型的方式。

private func createPath(_ departmentModel: RealmVendor) {
    let pathRef = FIRDatabase.database().reference().child(FirebaseDatabaseManager.DatabaseMainGateways.departmentsPath.rawValue).child(departmentModel.uid)
    pathRef.keepSynced(true)

    references.append(pathRef)

    let path = PathModel()
    path.email = departmentModel.email!
    path.mainVendorUID = departmentModel.mainVendorUID!

    let pathJSON = path.toJSON()

    pathRef.setValue(pathJSON) { (error, ref) in

    }
}

然后,当用户访问某个部门时,他只有两个字段,该字段输入电子邮件地址和密码。在他输入电子邮件后,我首先检查一系列路径中的电子邮件的可用性(以下称错误)。

func searchDepartmentPathModel(_ byEmail: String, success: (() -> Void)?, fail: ((_ error: Error) -> Void)?, notExist: (() -> Void)?) {

    let query = FIRDatabase.database().reference().child(FirebaseDatabaseManager.DatabaseMainGateways.departmentsPath.rawValue).queryOrdered(byChild: "email").queryEqual(toValue: byEmail)

    queries.append(query)

    query.observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.value is NSNull {
            debugPrint("searchDepartmentPathModel is NSNull there is not department path model", query.debugDescription)
            notExist?()
        } else {
            debugPrint("searchDepartmentPathModel is success", query.debugDescription)
            guard let _value = snapshot.value else { return }
            guard let valueDictionary = _value as? [String : [String : Any]] else { return }
            guard let modelDictionary = valueDictionary.first else { return }
            guard let path = Mapper<PathModel>().map(JSON: modelDictionary.value) else { return }

            // Saving department path
            let realmDepartmentManager = RealmDepartmentManager()

            realmDepartmentManager.saveDepartmentPath(path: path)

            success?()
        }
    }, withCancel: { (error) in
        fail?(error)
    })
}

如果此搜索找到带有此电子邮件的模型方式,我将首先尝试注册该用户,因为如果用户已注册,则返回特定的错误代码17007(这意味着该帐户中的条目不是第​​一个),我会用通常的输入调用其他函数。首次登录后,我会替换模型部门的ID(当您首次创建我生成的ID时,我会从Firebase设置用户ID)。

我们获得以下数据的结构

{
  "departmentsPath" : {
    "i11uK8erW2OYJPMQnnoOr0vRGca2" : {
      "email" : "apple@test.com",
      "mainVendorUID" : "V4lHBFY24rXTRrsvbZloYGjJwkZ2"
    }
  },
  "vendorDepartments" : {
    "V4lHBFY24rXTRrsvbZloYGjJwkZ2" : {
      "i11uK8erW2OYJPMQnnoOr0vRGca2" : {
        "createdAt" : "502381326.78624",
        "email" : "apple@test.com",
        "information" : {
          "address" : "3 Temasek Blvd, Suntec City, Suntec City Mall, Singapore 038983",
          "departmentTitle" : "Apple",
          "id" : "D8D7CC3A-E8CC-45AF-A71D-AAAB2E5F776F",
          "location" : {
            "id" : "D8D7CC3A-E8CC-45AF-A71D-AAAB2E5F776F",
            "latitude" : 1.2929781,
            "longitude" : 103.8570364
          },
          "phoneNumber" : "688",
          "storeManagerID" : "7",
          "storeManagerName" : "Tim"
        },
        "isCertified" : false,
        "isMain" : false,
        "mainVendorUID" : "V4lHBFY24rXTRrsvbZloYGjJwkZ2",
        "title" : "My Store",
        "uid" : "i11uK8erW2OYJPMQnnoOr0vRGca2"
      }
    }
  },
  "vendors" : {
    "V4lHBFY24rXTRrsvbZloYGjJwkZ2" : {
      "createdAt" : "502370885.980612",
      "departmentsEmails" : {
        "-KXzuTG8tZx9Fuyx3jJ8" : "apple@test.com"
      },
      "displayName" : “Alex”,
      "email" : “*******@gmail.com",
      "isCertified" : false,
      "isMain" : true,
      "photoPath" : "https://lh6.*****/-*/**/AAAAAAAAAA8/**/s96*c/photo.jpg",
      "title" : "My Store",
      "uid" : "V4lHBFY24rXTRrsvbZloYGjJwkZ2"
    }
  }
}

错误在于我无法找到模型的两种场景返回NSNull。第一种情况是,当用户第一次访问部门,从帐户中出来并尝试重新进入时,请求无法找到模型方式。第二种情况是,如果你去账户部门(第一次和后续访问),你就找不到建模的方法,并尝试登录未登录的部门中的另一个帐户。仅帮助从设备中删除应用程序。

1 个答案:

答案 0 :(得分:0)

在另一个案例中出现类似行为后,我现在描述一下。我有几个类别,以及标准类别设置为true的布尔值。我刚刚完全删除了类别的结构,但我回复了答案1或者true,它们已经安装,但必须返回NSNull。我认为问题出现在缓存中,在阅读this topic后证实了我的意见。我尝试以这种方式禁用缓存Firebase SDK FIRDatabase.database().persistenceEnabled = false(在此之前,值为true),在获得结果缓存后总是正确的。我想了解如何解决问题,以便您可以使用Firebase SDK缓存。