firebase swift queries in 查询性能

firebase swift queries in queries performance

我是 Firebase 的新手,对 Swift 比较陌生。

我的 firebase 设置如下。我有用户、关注者和被屏蔽的用户。我负责 UITableViewCell class 中的关注者。 在我进一步讨论之前,我想知道:将观察者放入查询中的观察者中如何影响性能。 (希望这些是正确的术语)。下面是正确的方法吗?(最有效的方法)。它有效,但似乎也有点结结巴巴。感谢任何反馈。

{
  "BlockedByUsers" : {
    "ba1eb554-9a81-4a74-bfd9-484a32eee13d" : {
    "97fee08f-19b2-4eb5-9eab-4b1985c22595" : true
    }
  },
 "Dates" : {
    "1457635040" : {
    "97fee08f-19b2-4eb5-9eab-4b1985c22595" : true
    },
  },
 "Locations" : {
    "97fee08f-19b2-4eb5-9eab-4b1985c22595" : {
    ".priority" : "u14dkwm41h",
    "g" : "u14dkwm41h",
    "l" : [ 51.05521018175982, 3.720297470654139 ]
    },
  },
 "Users" : {
   "97fee08f-19b2-4eb5-9eab-4b1985c22595" : {
   "blockedUsers" : {
      "ba1eb554-9a81-4a74-bfd9-484a32eee13d" : true
    },
   "following" : {
     "51879163-8b35-452b-9872-a8cb4c84a6ce" : true,
    },
   "fullname" : "",
   "dates" : 1457635040,
   "location" : "",
  },
 }
} 

我的 Swift 代码包含我担心的多个查询:

var usersRef: Firebase!
var userFollowingRef: Firebase!
var blockedByUsersRef: Firebase!
var datesRef: Firebase!
var geofireEndRef: Firebase!

var geoFireEnd: GeoFire? {

    return GeoFire(firebaseRef: geofireEndRef)
}

var dateRangeStart = Int()
var dateRangeEnd = Int()

override func viewDidLoad(){
    super.viewDidLoad()

    usersRef = DataService.ds.REF_USERS
    userFollowingRef = DataService.ds.REF_CURRENTUSER_FOLLOWING
    blockedByUsersRef = DataService.ds.REF_BLOCKED_BY_USERS
    datesRef = DataService.ds.REF_DATES
    geofireEndRef = DataService.ds.REF_GEOFIREREF_END
}

override func viewWillAppear(animated: Bool){
    super.viewWillAppear(animated)

    if userdefaultsUid != nil
    {
        geoFireEnd!.getLocationForKey(userID, withCallback: { (location, error) in
            if (error != nil)
            {
                print("An error occurred getting the location for \(self.userID) : \(error.localizedDescription)")

            } else if (location != nil)
            {
                self.updateUsersWithlocation(location)

            } else
            {
                print("GeoFire does not contain a location for \(self.userID)")

                self.updateUsersWithoutLocation()
            }
        })
    }
}

func updateUsersWithlocation(location: CLLocation)
{
    var allKeys = [String]()

    let locationQuery = self.geoFireEnd!.queryAtLocation(location, withRadius: 100.0)

    locationQuery.observeEventType(GFEventType.init(0), withBlock: {(key: String!, location: CLLocation!) in

        allKeys.append(key)

        self.datesRef.queryOrderedByKey().queryStartingAtValue(String(self.dateRangeStart)).queryEndingAtValue(String(self.dateRangeEnd)).observeEventType(.ChildAdded, withBlock: {
            snapshot in

            self.users.removeAll(keepCapacity: true)
            self.newKeys.removeAll()
            self.tableView.reloadData()

            for datesKey in snapshot.children
            {
                self.usersRef.childByAppendingPath(datesKey.key!).observeSingleEventOfType(.Value, withBlock: { snapshot in

                    if let key = datesKey.key where key != self.userID
                    {
                        if  allKeys.contains(key!) {

                            let newuser = FBUser(userKey: key!, dictionary: snapshot.value as! [String : AnyObject])

                            self.blockedByUsersRef.childByAppendingPath(key).childByAppendingPath(self.userID).observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in

                                if let _ = snapshot.value as? NSNull
                                {
                                    // we have not blocked  this one
                                    self.blockedByUsersRef.childByAppendingPath(self.userID).childByAppendingPath(key).observeSingleEventOfType(.Value, withBlock: { snapshot in

                                        if let _ = snapshot.value as? NSNull
                                        {
                                            // we are not blocked by this one
                                            if self.newKeys.contains(newuser.userKey) {}
                                            else
                                            {
                                                self.users.append(newuser)
                                                self.newKeys.append(newuser.userKey)
                                            }
                                        }
                                        self.tableView.reloadData()
                                    })
                                }
                            })
                        }
                    }
                })
            }
        })
    })
}

本质上,用户可以在特定日期出现在特定地点。他们记下了他们要去那里的日期,如下面的代码中所解释的。该日期可能与将要在该区域的其他用户重叠,时间范围为从前 7 天到后 21 天。这些用户可以被跟踪、屏蔽。但我正在让它们显示在 tableView 中。如果他们输入不同的日期或地点,则会弹出一组不同的用户。

    if let userStartDate = beginningDate as? Double
    {
        let intUserStartDate = Int(userStartDate)

        dateRangeStart = intUserStartDate - 604800

        dateRangeEnd = intUserStartDate + 1814400

        print(dateRangeStart, intUserStartDate, dateRangeEnd)

        updateUsers()
    }
    else
    {
        updateUsersWithoutDate()
    }

这可能根本不是答案或帮助,但我想把它扔在那里。

鉴于您真正想要寻找两件事:位置和时间,我们需要一些机制来处理它。

位置更静态;即保龄球盟友将永远是保龄球盟友,时代是动态的,我们需要一个范围。所以,给定一个结构

{
  "events" : {
    "event_0" : {
      "loc_time" : "bowling_5"
    },
    "event_1" : {
      "loc_time" : "tennis_7"
    },
    "event_2" : {
      "loc_time" : "tennis_8"
    },
    "event_3" : {
      "loc_time" : "dinner_9"
    }
  }
}

此结构处理这两个条件。您可以轻松查询在时间 7 有网球位置的所有节点。您还可以查询网球从开始时间 6 到结束时间 9 的范围,这将 return tennis_7 和tennis_8

这里有一些 ObjC 代码可以做到这一点

Firebase *ref = [self.myRootRef childByAppendingPath:@"events"];

FQuery *query = [[[ref queryOrderedByChild:@"loc_time"] 
                   queryStartingAtValue:@"tennis_6"] queryEndingAtValue:@"tennis_8"];

[query observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

    NSLog(@"%@", snapshot);

}];

您可以由此推断,用您的位置代替位置和距离,或者用时间​​戳代替时间。

另一个修改(这可能是显而易见的,但为了清楚起见而说明)是使用对您的位置的引用而不是实际名称(保龄球、网球);即

events
   "event_0" : {
      "loc_time" : "-JAY8jk12998f_20160311140200" // locationRef_timestamp
    },

locations
   -JAY8jk12998f : {
      "loc_name": "Fernando's Hideaway"
   }

以想要获取数据的方式构建数据可以显着减少代码(以及查询中查询等的复杂性)。

希望对您有所帮助。