多个 Geofire 查询和客户端过滤

Multiple Geofire queries and client-side filtering

几天来我一直在参考这个 SO post:

我的问题是,对于我的 iOS 应用程序,我需要制作一个按凭据排序的附近用户列表,例如:高级会员(最高且位于列表顶部)、捐赠者(下一个保费后最高),会员(basic/lowest)。

我在我的 Firebase 服务器中为 GeoFire 位置创建了 3 个条目,这些条目根据这些凭据拆分用户,因此需要 运行 3 个查询来检索它们。

GeoFire* geoFirePremium = [[GeoFire alloc] initWithFirebaseRef:[[[FIRDatabase database] reference] child:@"geofire-premium-members"]];
GeoFire* geoFireDonator = [[GeoFire alloc] initWithFirebaseRef:[[[FIRDatabase database] reference] child:@"geofire-donator-members"]];
GeoFire* geoFireRegular = [[GeoFire alloc] initWithFirebaseRef:[[[FIRDatabase database] reference] child:@"geofire-regular-members"]];
NSMutableDictionary* query1Items = [[NSMutableDictionary alloc] init];
NSMutableDictionary* query2Items = [[NSMutableDictionary alloc] init];
NSMutableDictionary* query3Items = [[NSMutableDictionary alloc] init];

CLLocation* coord = [[CLLocation alloc] initWithLatitude:34.2499 longitude:-85.4399]; // Test location
long searchDistance = 8;
float mile2Kilo = 1.60934;
float kilo2mile = 0.62137;
GFCircleQuery* query1 = [geoFirePremium queryAtLocation:coord withRadius:(CGFloat)(searchDistance * mile2Kilo)]; // Miles to Kilometers
[query1 observeEventType:GFEventTypeKeyEntered withBlock:^(NSString* key, CLLocation* location)
{
    // Store results in query1Items
}];
GFCircleQuery* query2 = [geoFireDonator queryAtLocation:coord withRadius:(CGFloat)(searchDistance * mile2Kilo)];
[query2 observeEventType:GFEventTypeKeyEntered withBlock:^(NSString* key, CLLocation* location)
{
    // Store results in query2Items
}];
GFCircleQuery* query3 = [geoFireRegular queryAtLocation:coord withRadius:(CGFloat)(searchDistance * mile2Kilo)];
[query3 observeEventType:GFEventTypeKeyEntered withBlock:^(NSString* key, CLLocation* location)
{
    // Store results in query3Items
}];

我的想法是添加一些代码来识别所有 3 个查询何时完成,然后将它们合并到 1 个列表中。

NSMutableDictionary* mergedItems = [[NSMutableDictionary alloc] init];
// For example:  { query1Items[], query2Items[], query3Items[], ... }

[query1 observeReadyWithBlock:^{
    NSLog(@"Query 1 is finished");
    // Check for queries 2 & 3 completion
    // Perform merge if all are completed
}];
[query2 observeReadyWithBlock:^{
    NSLog(@"Query 2 is finished");
    // Check for queries 1 & 3 completion
    // Perform merge if all are completed
}];
[query3 observeReadyWithBlock:^{
    NSLog(@"Query 3 is finished");
    // Check for queries 1 & 2 completion
    // Perform merge if all are completed
}];

所有 Firebase/GeoFire 引用的 JSON 结构如下:

- geofire-premium-members
    - userid
        - g: geohash
        - l
            - 0: lat
            - 1: lon

- geofire-donator-members   //same format

- geofire-regular-members   //same format

- users
    - userid
        - …

像这样使用多个查询是一种好方法吗?将来我可能需要添加更多凭据,但不知道我的方法是否可以很好地扩展。是否有更好的方法来实现我可能只使用单个查询的需求?我非常感谢任何见解

你的想法没有错。它可能过于复杂,因为有三个查询 return 相同类型的数据并在代码中组合数据并执行其他查询以获取其他用户数据。

即代码中的三个查询 return 一堆用户 ID,然后您需要对其进行更多查询以(例如)查找各个用户名

只要用户节点中的所有成员都具有相同的结构,您就可以将它们放在一个节点中并使用子节点 属性 来指示他们是哪种用户

userid_0
    name: "some name"
    user_type: "regular"
userid_1
    name: "another name"
    user_type: "donator"

然后GeoFire查询return指定半径内的所有用户。

假设无论如何都必须查找用户的姓名(作为示例),您将在用户节点中拥有其余数据并且可以简单地读入它们,按 user_type 排序(在代码中)并显示。

话虽这么说,但如果您确实知道要如何对它们进行排序,那么对结构进行简单的更改就可以轻松做到这一点。

userid_0
    name: "some premium name"
    user_type: 0
userid_1
    name: "a donator name"
    user_type: 1
user_id_2
    name: "regular name"
    user_type: 2

其中 0 = 高级用户,1 = 捐赠者用户,2 是普通用户。

然后代码排序的时候按user_type排序,premiums会浮到最前面