在 Firebase 中保存数组
Posted
技术标签:
【中文标题】在 Firebase 中保存数组【英文标题】:Saving Array in Firebase 【发布时间】:2016-07-14 08:38:56 【问题描述】:我使用 Firebase 3.0 作为我的后端,我需要将我的每个 user.uid
保存在一个单独的子节点中,该子节点需要是一个 NSArray,然后使用 for 循环检索该数组!
这就是我保存数据的方式:我为 FIRController 创建了一个单独的类,它处理数据库和存储的所有存储和检索。
func signUpUserWithBasicInfo(emailId : String! , password : String!, username : String!, age : String, gender : String!, backpackerType : String, info : [String : AnyObject], completionBlock : (() -> Void))
print("fir signup did recieve")
FIRAuth.auth()?.createUserWithEmail(emailId, password: password, completion:
user,error in
if error != nil
print("error encountered while backend email signup Handshake : \(error)")
print("")
self.delegate.firShowAlert("Error signing you up", Message: "Please check your network or this email already exist!")
else
print("uploading database")
self.profilePictureUploading(info, completionBlock:
FIRControllerClass.ref.child("UserProfile").child(user!.uid).setValue([
"username" : username,
"email" : emailId,
"age" : age,
"gender" : gender,
"password" : password,
"typeOfBackpacker" : backpackerType
])
completionBlock()
)
)
func profilePictureUploading(infoOnThePicture : [String : AnyObject],completionBlock : (()->Void))
if let referenceUrl = infoOnThePicture[UIImagePickerControllerReferenceURL]
print(referenceUrl)
let assets = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl as! NSURL], options: nil)
print(assets)
let asset = assets.firstObject
print(asset)
asset?.requestContentEditingInputWithOptions(nil, completionHandler: (ContentEditingInput, infoOfThePicture) in
let imageFile = ContentEditingInput?.fullSizeImageURL
print("imagefile : \(imageFile)")
let filePath = FIRAuth.auth()!.currentUser!.uid + "/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/\(imageFile!.lastPathComponent!)"
print("filePath : \(filePath)")
FIRControllerClass.storageRef.child("ProfilePictures").child(filePath).putFile(imageFile!, metadata: nil, completion: (metadata, error) in
if error != nil
print("error in uploading image : \(error)")
self.delegate.firShowAlert("Error Uploading Your Profile Pic", Message: "Please check your network!")
else
print("metadata in : \(metadata!)")
print(metadata?.downloadURL())
print("The pic has been uploaded")
print("download url : \(metadata?.downloadURL())")
self.uploadSuccess(metadata!, storagePath: filePath)
completionBlock()
)
)
else
print("No reference URL found!")
如何在我的后端创建一个用作数组的子节点,以及如何检索该数组?
我的 Firebase JSON 结构:-
"UserId" : [ 1,
"Sq5EDvVOsQWkLylEx3GrBdEsIN92",
"xC4jCJmobUcqghq8C3SI1XT0UPk1",
"D8QmnOSH6vRYiMujKNXngzhdn992",
"riHjon6wknOmALwf0Z0Ri5aOMA82",
"fKqlb88MKsYCE43xy7D51qH6jqH3",
"aCgAFAGDIgWRSUu9a2aMo9HtnnD3",
"iicKACGo8RaeTSEggKPB0sU2Bme2",
"qJ2c8AcEYzVkJKLl13N92tyKnbz2"
],
"UserProfile" :
"D8QmnOSH6vRYiMujKNXngzhdn992" :
"age" : "12",
"email" : "dummy1@gmail.com",
"gender" : "f",
"password" : "123454321",
"typeOfBackpacker" : "dummy",
"username" : "duummyy1"
,
"Sq5EDvVOsQWkLylEx3GrBdEsIN92" :
"age" : "121",
"email" : "ghfgh@gnag.com",
"gender" : "gjhg",
"password" : "123454321",
"typeOfBackpacker" : "chef",
"username" : "hgfgh"
,
"aCgAFAGDIgWRSUu9a2aMo9HtnnD3" :
"age" : "24",
"email" : "cathydurrant@gmail.com",
"gender" : "F",
"password" : "123454321",
"typeOfBackpacker" : "Group",
"username" : "Cathy"
,
etc
我还需要在我的数据库(数组)中添加一个 no of friends
数组。我使用 for 循环的唯一原因是,我可以向我的用户(除了他/她自己)显示每个用户的详细信息我在数据库中创建的 userId 数组,它实际上是每个用户数据库的父节点。
这就是我在我的数据库中添加UserId
的方式:-
func retrieveUserIdsArray(completionBlock : ((appendedArr : NSMutableArray) -> Void))
var appendedArray : NSMutableArray = []
FIRControllerClass.ref.child("UserId").observeEventType(FIRDataEventType.Value, withBlock: (snapshot) in
if let userIdDetails = snapshot.value as? NSMutableArray
userIdDetails.addObject((FIRAuth.auth()?.currentUser?.uid)!)
appendedArray = userIdDetails
completionBlock(appendedArr: appendedArray)
)
在这个函数中被调用:-
func signUpUserWithBasicInfo(emailId : String! , password : String!, username : String!, age : String, gender : String!, backpackerType : String, info : [String : AnyObject], completionBlock : (() -> Void))
print("fir signup did recieve")
FIRAuth.auth()?.createUserWithEmail(emailId, password: password, completion:
user,error in
if error != nil
print("error encountered while backend email signup Handshake : \(error)")
print("")
self.delegate.firShowAlert("Error signing you up", Message: "Please check your network or this email already exist!")
else
print("uploading database")
self.profilePictureUploading(info, completionBlock:
FIRControllerClass.ref.child("UserProfile").child(user!.uid).setValue([
"username" : username,
"email" : emailId,
"age" : age,
"gender" : gender,
"password" : password,
"typeOfBackpacker" : backpackerType
])
var a = 0
self.retrieveUserIdsArray( (appendedArr) in
a += 1
print("The appended array is : \(appendedArr)")
if a == 1
FIRControllerClass.ref.child("UserId").setValue(appendedArr)
else
completionBlock()
)
)
)
我使用a
变量的原因是为了解决它导致的无限循环(我知道它只是一个黑客,现在..)
欢迎任何更好的方法来解决这个问题!..
【问题讨论】:
数组在 Firebase(或任何 NoSQL 数据库)中可能非常具有挑战性,并且它们的使用非常具有情境性,因为通常有更好的选项来存储数据。此外,在 for..loop 中从 Firebase 读取数据并不是一个好主意,因为它绕过了 Firebase 的异步特性。你能提供一个以这种方式使用数组的用例吗? 我想将我的用户的 id 存储在一个特定的数组中,以便我可以在“查找朋友”部分中显示他们的详细信息!...我将他们的个人数据库保存在他们唯一的 user.uid 中作为“UserProfile”节点的子节点。我需要在一个页面中一次访问所有数据库,并在其他页面中应用地理定位算法和推荐引擎......这就是为什么我需要一个可以存储所有用户唯一 ID 的数组。 可能有更好的方法来做到这一点。您能否发布您的 Firebase 结构示例,以便我们查看您现在拥有的内容?请以文字形式发布,没有图像。您可以通过 Firebase 控制台->右侧的三个点->导出 JSON。 【参考方案1】:数组在 Firebase 中可能具有挑战性,因为无法直接访问或修改单个元素。您要么读取整个数组,要么写入整个数组。
我建议更改结构以更好地匹配您想要的数据并完全避免数组:
"UserProfile" :
"D8QmnOSH6vRYiMujKNXngzhdn992" :
"age" : "12",
"email" : "dummy1@gmail.com",
"gender" : "f",
"password" : "123454321",
"typeOfBackpacker" : "dummy",
"username" : "duummyy1"
"friend_count": 10
"friend_of"
"aCgAFAGDIgWRSUu9a2aMo9HtnnD3": true
,
然后一个简单的深度查询将返回您需要的一切(Firebase v2)
let myUid = "aCgAFAGDIgWRSUu9a2aMo9HtnnD3"
let path = ("friend_of/\(myUid)") // equals friend_of/aCgAFAGDIgWRSUu9a2aMo9HtnnD3
var userIdArray = [String]()
userProfileRef.queryOrderedByChild(path)
.queryEqualToValue(true)
.observeSingleEventOfType(.Value, withBlock: snapshot in
for child in snapshot.children
let userId = child.key as String
userIdArray.append(userId)
//loop is done, now we have an array of userIds that are friends
)
代码返回我的每个朋友的用户 (myUid)
我还添加了一个“朋友计数”节点,该节点仅记录该用户的朋友数量。添加朋友时,增加值,删除时减少。很快
myUid.child("friend_count").setValue(updated_count)
此代码还避免了循环、回调和额外的完成块,因为它依赖 Firebase 来获取数据,并在完成时通知我们。
如果你真的非常想读取数组节点(不推荐)
let myRef = self.myRootRef.child("array_node")
myRef.observeSingleEventOfType(.Value, withBlock: snapshot in
let a = snapshot.value as! NSArray
print(a) //a an NSArray
let b = (a as Array).filter $0 is String
print(b) //b is a Swift Array
print( b[1] )
)
【讨论】:
let myUid = "aCgAFAGDIgWRSUu9a2aMo9HtnnD3"
是你硬编码的东西,我需要每个 user.uid 来填充我的 tableView。这就是我首先将每个用户的 uid 存储在数组中的原因.顺便说一句,谢谢你的帮助!
@AchintyaGupta 我将其硬编码为示例 uid。这将是从 Firebase auth 变量派生的当前登录用户的 uid。以上是关于在 Firebase 中保存数组的主要内容,如果未能解决你的问题,请参考以下文章
从 Firebase 读取数据并将其保存到数组中 - React
Firebase 引用对象不会保存到 SwiftUI 中的变量