ios - 处理 Firebase 查询中由于元素数量较多而导致的内存使用情况

标签 ios swift firebase firebase-realtime-database

我正在编写代码,将 firebase 中的元素附加到数组中,以使用文本字段执行简单搜索。

该方法的代码如下:

 var filteredEvents = [Event]()
var eventsArray = [Event]()
fileprivate func fetchEvents(){
    print("Fetching events....")
    //create a reference to the location in the database that you want to pull from and observe the value there
    let ref = Database.database().reference().child("events")
    // this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
    ref.observe(.value, with: { (snapshot) in
        guard let dictionaries = snapshot.value as? [String: Any] else{
            return
        }
        //does the job of sorting dictionary elements by key and value
        //displaying the key and each corresponding value
        dictionaries.forEach({ (key,value) in
           // print(key, value)
            //creating an eventDictionary to store the results of previous call
            guard let eventDictionary = value as? [String: Any] else{
                return
            }
            //will cast each of the values as an Event based off my included struct
            //Make sure to create a model it is the only way to have the data in the format you want for easy access
             let events = Event(currentEventKey: key, dictionary:eventDictionary)
            // appends that to the dictionary to create the dictionary of events
            self.eventsArray.append(events)
        })
        // will sort the array elements based off the name
        self.eventsArray.sort(by: { (event1, event2) -> Bool in
            return event1.currentEventName.compare(event2.currentEventName) == .orderedAscending
        })
        // will again reload the data
        self.collectionView?.reloadData()

    }) { (err) in
        print("Failed to fetch events for search")
    }
}

我个人并没有想到我可能会有很多事件。我无法将所有 1000 多个事件附加到字典中。这会增强我的内存力。无论如何,我可以让查询响应文本字段吗?另外,任何人都可以帮助我完成执行此操作但不会破坏我的内存的查询行吗?

"events" : {
"CCDS" : {
  "attend:count" : 1,
  "event:date" : {
    "end:date" : "08/09/2017",
    "end:time" : "7:00 PM",
    "start:date" : "08/09/2017",
    "start:time" : "5:00 PM"
  },
  "event:description" : "Happy hour is more joyful in the summer thanks to Center City District Sips, which offers discounted drinks and appetizers every Wednesday evening.  Catch up with old friends and make a few new ones as Center City’s best bars and restaurants host the summer’s happiest hour every Wednesday from 5-7 p.m.  Enjoy $5 cocktails, $4 wine, $3 beers and half-price appetizers at dozens and dozens of bars and restaurants.",
  "event:imageURL" :someURL",
  "event:location" : {
    "event:city" : "Philadelphia",
    "event:state" : "PA",
    "event:street:address" : "660 Chestnut St",
    "event:zip" : 19106
  },
  "event:name" : "Center City District Sips"
},
"MIA" : {
  "attend:count" : 1,
  "event:date" : {
    "end:date" : "09/03/2017",
    "end:time" : "7:00 PM",
    "start:date" : "09/02/2017",
    "start:time" : "12:00 PM"
  },
  "event:description" : "Budweiser Made in America Festival is an annual music festival held in Philadelphia and formerly simultaneously held in Los Angeles.Sponsored by Anheuser–Busch and produced by Live Nation, the event features several stages that continuously host live music from a wide range of genres including hip hop, rock, pop, R&B, and EDM.",
  "event:imageURL" : "someURL",
  "event:location" : {
    "event:city" : "Philadelphia",
    "event:state" : "PA",
    "event:street:address" : "Ben Franklin Parkway",
    "event:zip" : 19130
  },
  "event:name" : "Made In America"
}
  },

例如,我想提取有关我使用查询搜索的事件的所有信息。因此,如果我开始输入“美国制造”,它将从“事件”选项卡中提取有关该事件的所有相关信息

这就是我现在拥有的

fileprivate func fetchEvents(searchString: String){
    print("Fetching events....")
    //create a reference to the location in the database that you want to pull from and observe the value there
    let ref = Database.database().reference().child("events")
    // this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
  let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)
    print(query)
    query.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String: Any] else{
            print(snapshot.value)
            return
        }
        print(snapshot.value)
    }) { (err) in
        print("Failed to fetch event data", err)
    }

}

返回这个

(/events { ep = Made In America; i = "event:name"; sp = Made In America; })

最佳答案

看来问题是

"How can I query for a value contained in a child node?"

给出与原始结构相似的结构

"events" : {
  "CCDS" : {
    "attend:count" : 1,
    "event:imageURL" :"someURL",
    "event:name" : "Center City District Sips"
  "MIA" : {
    "attend:count" : 1,
    "event:imageURL" : "someURL",
    "event:name" : "Made In America"

Firebase 查询将返回您想要的节点。

如果用户输入“Made In America”并点击搜索按钮,则此处的查询将在快照中返回该节点。

let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqualTo(searchString)
query.observeSingleEvent(of: .value, with: { (snapshot) in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        let eventDict = snap.value as! [String: Any]
        let attendCount = eventDict["attend:count"] as! String
        let url = eventDict["event:imageURL"} as! String
    }
})

如果您想要进行部分字符串匹配,用户只需输入几个字符,例如 Made,代码类似,但您需要让 firebase 返回以 Made 开头的所有匹配项...

查询看起来像这样

let startString = "Made"
let endString = "Made" + "\\uf8ff"
let query = ref.queryOrdered(byChild: "event:name")
                        .queryStarting(atValue: startString)
                        .queryEnding(atValue: endString")

“\uf8ff”是 Unicode 中代码级别非常高的字符 - 因为它包含所有前面的字符。

但是,“即时”查询可能会导致用户界面无响应或缓慢,因此不建议这样做。

另一种方法是创建一个单独的节点,其中包含的信息要少得多,并包含用户将搜索的元素以及对事件节点的引用。

因此包含所有数据的主节点如下所示

"events" : {
  "-uyuh8s8j8jsdas" : {
    "event": "CCDS"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
  "-y88jsijsijjids" : {
    "event": "MIA"
    "attend:count" : 1,
    "event:imageURL" : "someURL",

“较小”的节点看起来像这样

   events_for_searching
       -uyuh8s8j8jsdas
         event:name: "Center City District Sips"
       -y88jsijsijjids
         event:name: "Made In America"

有了这个,您可以将 events_for_searching 中的所有节点加载到一个数组中(然后根据用户类型过滤该数组),这将使 UI 非常敏感,并且当用户选择名称时,您可以使用键从该节点作为引用,通过observeSingleEvent 函数从事件节点加载数据。

编辑

为了回应评论,我想在代码中添加更多细节。

这是我的结构

  "events" : {
    "event_0" : {
      "event:name" : "An Event"
    },
    "event_1" : {
      "event:name" : "Made In America"
    }
  },

以及查询事件的代码:名称:美国制造

let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)

query.observeSingleEvent(of: .value, with: { (snapshot) in
    guard let dictionary = snapshot.value as? [String: Any] else{
        print(snapshot.value)
        return
    }
    print(snapshot.value)
}) { (err) in
    print("Failed to fetch event data", err)
}

和输出

Optional({
    "event_1" =     {
        "event:name" = "Made In America";
    };
})

关于ios - 处理 Firebase 查询中由于元素数量较多而导致的内存使用情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54028155/

相关文章:

ios - 如何将图像用作 map ?

ios - UIView 动画以错误的属性值开始

ios - Swift 错误 : "Cannot find interface declaration for ' SKScene', 的父类(super class)”

javascript - 如何从firestore获取数据到谷歌云功能?

javascript - firebase 函数属性 'data' 在类型 'Change<DataSnapshot>' 上不存在

ios - iPhone X 横向的 UICollectionView

ios - 为什么 9 月的月份会在我的时差方法中增加五个小时?

ios - 在多个 ViewController 上共享 ARSCNView

swift - 如何使用firebase在ios中实现私聊

javascript - PhoneGap 垃圾收集