簡體   English   中英

使用Swift在Firebase中保存現有的JSON文件?

[英]Saving an existing JSON file in Firebase using Swift?

我有一個JSON文件,保存在本地項目中。 現在,我很好奇將其保存在Firebase中。 我知道Firebase以NoSQL格式(作為JSON)保存數據。 我看過一些有關向Firebase添加文件的教程(經過一些操作,例如在示例iOS應用程序中點擊按鈕)。 但是是否可以將整個JSON文件本身(不僅僅是其中的一部分)保存在firebase中,最初(不是在點擊某些按鈕之后),然后加載該文件,因為在我的項目中用戶無法自己添加文件? 該應用程序應從JSON文件加載數據。 我是Firebase的新手,所以我幾乎沒有使用它的經驗。 如果您有任何建議或知道如何操作,我們將不勝感激。

編輯好,以澄清我在問什么。 我有一個包含文本文件的項目,其中包含JSON數據。 最初,我將其添加到我的項目中是因為我沒有使用Firebase,AWS等的經驗。我只需要查看應用程序對數據的反應即可。 將來數據將顯着增長,因此顯然我不會將其保存在項目中。 問題是,我只想將JSON數據保存在Firebase中。 而且我不知道正確的方法:僅導入JSON或從頭開始編寫(通過編程方式或在控制台中)。 另外,我想知道這通常是否是一個好主意,因為這是我第一次使用在線數據庫,並且許多人說Firebase是最好的數據庫。 我對這些東西真的很陌生,這就是為什么我要問這樣的問題。

EDITED_2

{
"list": {
    "restaurants": [{
                    "id": "231311234342bn123",
                    "name": "Grand Royal",
                    "suggested": true,
                    "address": {
                    "longitude": "30.31527",
                    "latitude": "59.93688",
                    "formatted": ["Nevskiy prospekt 10, Saint Petersburg",
                                  "Russian Federation"
                                  ]
                    },
                    "tags": ["fish",
                             "Italian",
                             "Friends"
                             ],
                    "category": "$$$$",
                    "description": "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.",
                    "shortDescription": "an",
                    "collectionName": "Relaxing with friends",
                    "distance": "1324",
                    "country": "Russian Federation",
                    "Region": "North-West region",
                    "city": "Saint Petersburg"
                    },

                    {
                    "id": "123234344t5213",
                    "name": "N",
                    "image": "A",
                    "suggested": true,
                    "address": {
                    "longitude": "30.31821",
                    "latitude": "59.93605",
                    "formatted": ["Nevskiy prospekt 15, Saint Petersburg",
                                  "Russian Federation"
                                  ]
                    },
                    "tags": ["fish",
                             "french",
                             "family"
                             ],
                    "category": "$$$$",
                    "description": "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. ",
                    "shortDescription": "ab",
                    "collectionName": "Evening with a family",
                    "distance": "556",
                    "country": "Russian Federation",
                    "Region": "North-West region",
                    "city": "Saint Petersburg"
                    }]}}

這是我的初始JSON數據的一小段(例如,尚未完成,例如,此時圖像僅包含一個字符串)。 數據在整個應用程序中使用(在表格視圖,單獨的視圖等中)。 例如,我用它來填充表格視圖,在mapView和其他UIViewController子類中使用它。 另外,我需要過濾和搜索它的能力。 目前,我正在通過解碼整個JSON並將其添加到數組中來進行此操作,然后過濾該數組。 但是我想,當您的圖像中包含大量數據時,這不是最佳選擇。

還有一點是,在Core Data中可以設置批處理請求,因此它最初只會獲取一定數量的數據。 它可以很好地用於表格視圖,因為在滾動表格視圖時, Core Data自動獲取新數據以填充單元格。 是否可以使用firebase進行類似的操作,還是應該一次讀取所有數據?

我還讀到Firebase不需要保存類似數組的數據,但是有幾種方法可以解決該問題。 這對我很重要,因為我確實需要將部分數據存儲在數組中。

希望這會提供一些方向,請原諒。

最棒的是,通常有比數組更好的方法將數據存儲在Firebase中。 數組不可搜索,不可編輯或不可添加,如果要更改某些內容,則需要覆蓋整個數組。 請參閱“ 數組很邪惡”

其次,在Firebase中對數據進行非規范化是正常的。 這意味着當數據太“深”時,查詢所需的數據就困難得多。 通常,奉承會更好-取決於您要從Firebase中獲得什么。

第三項是處理問題數據的100種不同方式,我將介紹兩種。 一個在概念上演示如何寫入數據,第二個可能是更好的選擇。

這是一種以蠻力方式寫入數據的方法

let addressDict = [
    "longitude": "30.31527",
    "latitude": "59.93688",
    "formatted1": "Nevskiy prospekt 10, Saint Petersburg",
    "formatted2": "Russian Federation"
]

let tagsDict = [
    "fish": true,
    "italian": true,
    "friends": true
]

let restaurantDict = [
    "name": "Grand Royal",
    "suggested": true,
    "address": addressDict,
    "tags": tagsDict,
    "category": "$$$$",
    "description": "Lorem ipsum dolor si.",
    "shortDescription": "an",
    "collectionName": "Relaxing with friends",
    "distance": "1324",
    "country": "Russian Federation",
    "Region": "North-West region",
    "city": "Saint Petersburg"
    ] as [String : Any]

let restaurantsRef = self.ref.child("restaurants").childByAutoId()
restaurantsRef.setValue(restaurantDict)

運行此代碼將產生與您的結構相似的JSON結構。 請注意,飯店密鑰(KzEIkF6nxgWH1nA8B2D)是在寫入數據時自動創建的,因此,飯店的其他結構將通過其鍵來引用飯店。

"restaurants" : {
    "-KzEIkF6nxgWH1nA8B2D" : {
      "Region" : "North-West region",
      "address" : {
        "formatted1" : "Nevskiy prospekt 10, Saint Petersburg",
        "formatted2" : "Russian Federation",
        "latitude" : "59.93688",
        "longitude" : "30.31527"
      },
      "category" : "$$$$",
      "city" : "Saint Petersburg",
      "collectionName" : "Relaxing with friends",
      "country" : "Russian Federation",
      "description" : "Lorem ipsum dolor si.",
      "distance" : "1324",
      "name" : "Grand Royal",
      "shortDescription" : "an",
      "suggested" : true,
      "tags" : {
        "fish" : true,
        "friends" : true,
        "italian" : true
      }
    }
  },

要查詢所有$$$$餐廳:

//print all restaurants with $$$$
let restRef = self.ref.child("restaurants")
let query = restRef.queryOrdered(byChild: "category").queryEqual(toValue: "$$$$")
query.observeSingleEvent(of: .value) { snapshot in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        print(snap)
    }
}

雖然我們可以查詢所有類別==“ $$$$”的餐廳,但是地址和標簽節點太深(實際上並不准確,請參閱Deep Query ,但是在本示例中將其繼續進行)這個概念是合理的)。

所以更好的結構是

"restaurants" : {
    "-KzEIkF6nxgWH1nA8B2D" : {
      "Region" : "North-West region",
      "category" : "$$$$",
      "city" : "Saint Petersburg",
      "collectionName" : "Relaxing with friends",
      "country" : "Russian Federation",
      "description" : "Lorem ipsum dolor si.",
      "distance" : "1324",
      "name" : "Grand Royal",
      "shortDescription" : "an",
      "suggested" : true,
    }
  },

"addresses"
   "-KzEIkF6nxgWH1nA8B2D"
        "formatted1" : "Nevskiy prospekt 10, Saint Petersburg",
        "formatted2" : "Russian Federation",
        "latitude" : "59.93688",
        "longitude" : "30.31527"

"tags"
   "-KzEIkF6nxgWH1nA8B2D"
        "fish" : true,
        "friends" : true,
        "italian" : true

以及創建它的代碼:

let restDict = [
    "name": "Jay's Eatery",
    "category": "$$$$"
]

let addressDict = [
    "formatted1": "Anytown"]

let tagsDict = [
    "fish": true,
    "friends": true,
    "italian": true
]

let restRef = self.ref.child("restaurants")
let addressesRef = self.ref.child("addresses")
let tagsRef = self.ref.child("tags")

let thisRestaurantRef = restRef.childByAutoId()
thisRestaurantRef.setValue(restDict, withCompletionBlock: { (error, snapshot) in
    if error == nil {
        let thisRestaurantKey = snapshot.key
        addressesRef.child(thisRestaurantKey).setValue(addressDict)
        tagsRef.child(thisRestaurantKey).setValue(tagsDict)
    }
})

現在,您可以使用上面的查詢輕松地查詢帶有魚,緯度以59開頭或Grand Royal名稱的餐廳。

如您所見,將數據存儲在Firebase中時,不會涉及編碼或解碼。

是的,Firebase可以批量加載數據以填充要用作tableView數據源的數組

最佳實踐是創建代表代碼中和用戶數據的類對象,並利用Firebase的背面存儲該數據。

class RestaurantClass {
    key = "" //"-KzEIkF6nxgWH1nA8B2D"
    name = "" //"Grand Royal
    etc

    func init(withSnapshot: DataSnapshot) {
      //populate the class vars from the snapshot
}

然后,查詢$$$$餐廳的查詢將是這樣的:

let restRef = self.ref.child("restaurants")
let query = restRef.queryOrdered(byChild: "category").queryEqual(toValue: "$$$$")
query.observeSingleEvent(of: .value) { snapshot in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        let rest = RestaurantClass(withSnap: snap)
        self.myTableViewDataSourceArray.append(rest)
    }
    self.myTableViewDataSourceArray.reloadData()
}

還有很多,但這應該可以使您朝正確的方向前進。

從這個答案中獲得的好處是可以利用Firebase在后端上存儲原始數據-如果數據的結構正確,它可以以極快的速度,可擴展性和可維護性進行存儲。 在代碼中使用使用該后端數據填充的類作為數據源,並將數據呈現給用戶。

最后要注意的是,如果您正在使用位置,則需要一種工具來簡化操作。 請查看GeoFire了解更多信息。

編輯:

處理評論以進行澄清。

您不會像在類或結構中創建屬性那樣在代碼中完全創建Firebase數據結構,這完全不像是帶有標頭的空SQL表。 您還可以通過更多方式告訴Firebase如何寫入該數據。 因此,例如:

ref.child("users").child("uid_0").setValue("Leroy")

告訴Firebase在用戶節點內,編寫一個key:value字符串對:uid字符串:Leroy,如下所示:

users
  uid_0: "Leroy"

let aDict = ["user_name": "Leroy"]
ref.child("users").child("uid_0").setValue(aDict)

會導致告訴Firebase在用戶節點內編寫一個key:字符串對值:uid:aDict字典。 請注意,aDict是鍵:值對本身,它是字符串:字符串(例如,user_name:Leroy)

users
  uid_0
    user_name: "Leroy"

我喜歡認為Firebase是一個很大的鍵字典:值對,其中鍵始終是字符串(避免使用數組!),值是任何類型,可以是字符串,整數等或其他Dictionary。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM