2016-12-20 4 views
0

В настоящее время я работаю над проектом, который позволяет пользователям арендовать дополнительные места. Вы можете думать, что клоун airbnb. В этом приложении iOS я использую Firebase для Back-end как сервис.Извлечение данных из Firebase длится быстро Swift

Я хочу получить квартиры, которые удовлетворяют параметрам фильтрации, таким как: количество кроватей, количество спален, курение и т. Д. Логически, я группирую все квартиры по временным интервалам сначала, а затем наборы квартир удовлетворяют фильтрованный город, m выборки квартир, которые удовлетворяют фильтрам. Затем я повторяю все квартиры один за другим, чтобы получить их изображения.

Мои Json дерево как:

filter_flats/FlatCity/FlatID 
time_slots/timestamp/flatID:true 
flat_images/FlatID 

Вот что я хочу:

import Foundation 
import Firebase 
import FirebaseStorage 

protocol QuerymasterDelegate :class 
{ 
    func getFilteredFlats(filter:FilterModel, completion: @escaping ([FilteredFlat]) ->()) 
} 



class Querymaster:QuerymasterDelegate 
{ 
    var flatEndpoint = FIRFlat() 

    var returningFlats = [FilteredFlat]() 
    ///////////////////////////////////////////////////////////// 
    //MARK: This method pulls all flats with required timeslot.// 
    ///////////////////////////////////////////////////////////// 
    internal func getFilteredFlats(filter: FilterModel, completion: @escaping ([FilteredFlat]) ->()) { 

     var zamanAraliginaUygunFlatlar = [String]() 

     FIRREF.instance().getRef().child("time_slots").queryOrderedByKey().queryStarting(atValue: filter.fromDate?.toTimeStamp()).queryEnding(atValue: filter.toDate?.toTimeStamp()).observeSingleEvent(of: .value, with: { (ss) in 
      for ts in ss.children.allObjects 
      { 
       let timeslotFlatObj = ts as! FIRDataSnapshot 
       let timeslotForFlat = timeslotFlatObj.value as! [String:Bool] 
       for x in timeslotForFlat 
       { 
        if (x.value == true && !zamanAraliginaUygunFlatlar.contains(x.key)) 
        { 
         zamanAraliginaUygunFlatlar.append(x.key) 
        } 

       } 
      } 

      ///////////////////////////////////////////////////////// 
      //MARK: This method pulls all flats with filtered city.// 
      ///////////////////////////////////////////////////////// 

      FIRREF.instance().getRef().child("filter_flats/" + filter.city!).observe(.value, with: { (ss) in 

       var sehirdekiFlatler = [String:Flat]() 

       for i in ss.children.allObjects 
       { 
        let flt = Flat() 
        let flatObject = i as! FIRDataSnapshot 
        let mainDict = flatObject.value as! [String:Any] 
        flt.userID = (mainDict["userId"] as? String)! 
        flt.id = flatObject.key 
        flt.city = filter.city 
        flt.title = mainDict["title"] as? String 
        flt.bathroomCount = mainDict["bathroomCount"] as? Int 
        flt.bedCount = mainDict["bedCount"] as? Int 
        flt.bedroomCount = mainDict["bedroomCount"] as? Int 
        flt.internet = mainDict["internet"] as? Bool 
        flt.elevator = mainDict["elevator"] as? Bool 
        flt.heating = mainDict["heating"] as? Bool 
        flt.gateKeeper = mainDict["gateKeeper"] as?Bool 
        flt.parking = mainDict["parking"] as? Bool 
        flt.pool = mainDict["pool"] as? Bool 
        flt.smoking = mainDict["smoking"] as? Bool 
        flt.tv = mainDict["tv"] as? Bool 
        flt.flatCapacity = mainDict["capacity"] as? Int 
        flt.cooling = mainDict["cooling"] as? Bool 
        flt.price = mainDict["price"] as? Double 
        flt.washingMachine = mainDict["washingMachine"] as? Bool 

        sehirdekiFlatler[flt.id] = flt 

        if(!(zamanAraliginaUygunFlatlar).contains(flt.id)) 
        { 
         if(filter.bathroomCount == nil || filter.bathroomCount! <= flt.bathroomCount!) 
         { 
          if(filter.bedCount == nil || filter.bedCount! <= flt.bedCount!) 
          { 
           if(filter.bedroomCount == nil || filter.bedroomCount! <= flt.bedroomCount!) 
           { 
            if(filter.internet == false || filter.internet! == flt.internet!) 
            { 
             if(filter.elevator == false || filter.elevator! == flt.elevator!) 
             { 
              if(filter.heating == false || filter.heating! == flt.heating!) 
              { 
               if(filter.gateKeeper == false || filter.gateKeeper! == flt.gateKeeper!) 
               { 
                if(filter.parking == false || filter.parking! == flt.parking!) 
                { 
                 if(filter.pool == false || filter.pool! == flt.pool!) 
                 { 
                  if(filter.smoking! == false || filter.smoking! == flt.smoking!) 
                  { 
                   if(filter.tv! == false || filter.tv! == flt.tv!) 
                   { 
                    if(filter.capacity == nil || filter.capacity! <= flt.flatCapacity!) 
                    { 
                     if(filter.cooling == false || filter.cooling! == flt.cooling!) 
                     { 
                      if(filter.priceFrom == nil || filter.priceFrom! <= flt.price!) 
                      { 
                       if(filter.priceTo == nil || filter.priceTo! >= flt.price!) 
                       { 
                        if(filter.washingMachine == false || filter.washingMachine! == flt.washingMachine!) 
                        { 
                         let filteredFlat = FilteredFlat() 
                         filteredFlat.flatCity = flt.city 
                         filteredFlat.flatID = flt.id 
                         filteredFlat.flatPrice = flt.price 
                         filteredFlat.flatTitle = flt.title 
                         filteredFlat.userID = flt.userID 
                         self.returningFlats.append(filteredFlat) 


                        } 
                       } 
                      } 
                     } 
                    } 
                   } 
                  } 
                 } 
                } 
               } 
              } 
             } 
            } 
           } 
          } 
         } 
        } 
       } 
       //////////////////////////////////////////////////////////////// 
       //MARK: This method pulls thumbnail image for returning Flats.// 
       //////////////////////////////////////////////////////////////// 
       if self.returningFlats.count > 0 
       { 
        for a in self.returningFlats 
        { 
         FIRREF.instance().getRef().child("flat_images/" + a.flatID!).observeSingleEvent(of: .value, with: { (ss) in 
          let dict = ss.children.allObjects[0] as! FIRDataSnapshot 
          let obj = dict.value as! [String:String] 
          let flatImageDownloaded = FlatImageDownloaded(imageID: dict.key, imageDownloadURL: obj["downloadURL"]!) 
          a.flatThumbnailImage = flatImageDownloaded 
          completion(self.returningFlats) 
         }) 
        } 
       } 
      }) 
     }) 
    } 
} 

Отмеченный код This method pulls thumbnail image for returning Flats. обычно выборки данных медленнее из-за прыжков между узлами квартир.

Я не понял, что я делаю неправильно. Можете ли вы предложить более эффективный метод?

Заранее спасибо.

+0

Загрузка данных из базы данных Firebase обычно является простым вопросом о вашей доступной полосе пропускания и количестве данных, которые вы загружаете. Задержка часто не является проблемой, поскольку [запросы трубопроводов Firebase по возможности] (http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using -query-вместо-оф-OBSE/35932786 # 35932786). Сколько данных вы загружаете по какой пропускной способности и сколько времени потребуется? Можете ли вы [воспроизвести более простой фрагмент кода и поделиться JSON (как текст)] (http://stackoverflow.com/help/mcve)? –

ответ

0

Это похоже на то, что вы работаете со значительным объемом данных, и мы не знаем вашего текущего пользовательского интерфейса, но это может быть место, чтобы начать уменьшать пропускную способность и ускорять работу.

Например, в пользовательском интерфейсе есть три кнопки, которые активируются, когда пользователь выбирает предыдущий.

Select City <- highlighted and ready to be tapped 
Select Bedrooms <-Dimmed and not available yet 
Select Internet <-Dimmed and not available yet 

Когда пользователь выбирает «Выбрать город», им предоставляется список доступных городов. это простой и быстрый запрос Firebase.

Они нажимают Select Спальни и выбирают 2. Никакого реального запроса здесь еще нет, так как это число от 1 до 5 (например).

Они выбирают Интернет, и это Да/Нет, а может быть, Нет/Набрать/Широкополосный доступ.

Теперь вот ключ - структура.

City0 
    name: "some city" 

Flats 
    flat_0 
    location: "City0" 
    bedrooms: "2" 
    internet: "Broadband" 
    filter: "City0_2_Broadband" 
    flat_1 
    location: "City0" 
    bedrooms: "4" 
    internet: "Dial up" 
    filter "City0_4_Dial up" 

с этим, вы можете искать любой город или любое количество спален или любого интернета в качестве отдельных запросов.

Реальная власть имеет возможность выполнять SQL-подобный запрос «и», когда вы хотите получить очень конкретные данные; которые квартир доступны и 4 спальни и дозвона и в city0

query for: "City0_4_Dial up" 

очень быстрый и гибкий, и вы можете создать критерии запроса в пользовательском интерфейсе, который ограничивает количество данных, поступающих в приложение от Firebase, что делает его очень быстрым.

Если это слишком далеко от базы, сообщите мне, и я отредактирую и предоставил другой вариант.

+0

Этот apporach довольно гибкий, который уже думает моя команда. Но есть трюк об фильтрации. Например, если мы ищем такой запрос, как City0_4_Dialup, наш пользовательский интерфейс должен предоставлять квартиры, которые удовлетворяют квартирам, которые удовлетворяют параметрам запроса city0_4_dialup, но наш ui должен предоставлять квартиры, если пользователь не выбирает, например, спальни или интернет, поэтому мы возьмите их как «Не имеет значения» и покажет квартиры, есть ли у них интернет, спальни или нет. Для простого понимания наша логика добавляется, верна или не имеет значения, как в Airbnb. –

+0

Также, если пользователь ищет квартиры, которые имеют 4 спальни, квартиры, которые имеют 5,6,7,8,9 ... n спальни, должны быть представлены на нашем пользовательском интерфейсе. Эти требования к запросам приводят нас к путанице в отношении Firebase, у которой нет мощного двигателя запросов, в отличие от классических реляционных двигателей. –

0

Firebase использует базу данных NoSQL, поэтому типичный запрос будет очень неэффективным. Насколько я понимаю, ваше приложение требует много запросов для данных, поэтому сама Firebase не идеальное решения для вашего приложения, я думаю ..

Во всяком случае, в коде, вы можете просто запросить изображения в Dispatch async блок, и это ускорит процесс. Кроме того, fyi, сохраняя изображения в FirebaseStorage и сохраняя URL-адрес в базе данных Firebase, поможет вам уменьшить количество денег на данные.

Смежные вопросы