由于Firebase查询中的大量元素而处理内存使用情况 [英] Dealing with memory usage due to high element count in Firebase query

查看:36
本文介绍了由于Firebase查询中的大量元素而处理内存使用情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing code that is appending elements from firebase to an array to perform a simple search using a textfield.

该方法的代码如下:

 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多个事件附加到字典中.那会刺痛我的记忆.无论如何,我可以让查询响应文本字段.有人还能帮我完成执行该操作但不会破坏我的记忆的查询行吗?

I personally did not think of the chance where I may have a great number of events. I won't be able to just append all 1000+ events to a dictionary. That will ratchet my memory up. Is there anyway I could have the query respond to the text field. Also could anyone maybe help me with the line for the query that would perform this action but not destroy my memory?

"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"
}
  },

例如,我想提取有关使用查询搜索的事件的所有信息.因此,如果我开始输入美国制造",它将从事件"标签中提取有关该事件的所有相关信息

For example I want to pull all information about an event that I have searched for using the query. So if I begin to type in Made in America it will pull all relevant information from the events tab about that event

这是我目前拥有的

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?"

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

Given a structure similar to the original

"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查询将返回您想要的节点.

a Firebase query would return the node you want.

如果用户键入 Made In America 并点击了搜索按钮,则系统会在查询中返回该节点的快照.

If the user typed in Made In America and tapped the search button here's the query to return that node in a snapshot.

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开头的匹配项...

If you want to do a partial string match, where the user could type in just a few characters like Made the code is similar but you need to let firebase return all of the matches starting with Made...

查询看起来像这样

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

"\ uf8ff"是Unicode中具有很高代码级别的字符-因为它包含了所有前面的字符.

The "\uf8ff" is a character at a very high code level in Unicode - because of that it encompasses all of the preceeding characters.

但是,即时"查询会创建无响应或反应迟缓的UI,因此不建议这样做.

However, querying 'on the fly' can create an unresponsive or sluggish UI so it's not recommended.

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

An alternative is to create a seperate node that contains a lot less info and contains the elements the user would search for and a reference to the event node.

所以包含所有数据的主节点看起来像这样

So the main node containing all the data looks like this

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

一个较小"的节点看起来像这样

and a 'smaller' node would look like this

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

这样,您可以将events_for_searching中的所有节点加载到一个数组中(然后根据用户类型过滤该数组),这将使UI响应迅速,并且当用户选择名称时,您可以使用键以该节点为参考,以通过observeSingleEvent函数从事件节点加载数据.

With this, you could load all of the nodes from the events_for_searching into an array (then filter the array as the user types) which would make the UI very responsive and when the user selects a name, you can then use the key from that node as a reference to load the data from the events node via an observeSingleEvent function.

编辑

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

In response to a comment, I wanted to add a bit more detail in code.

这是我的结构

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

以及用于查询事件的代码:名称:Made In America

and the code to query for 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";
    };
})

这篇关于由于Firebase查询中的大量元素而处理内存使用情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆