在 Swift 中使用 GeoFire 查询不会提供有用的输出

Using GeoFire queries in Swift does not give useful output

我现在非常绝望,因为我正试图在我的 Firebase 数据库上使用 GeoFire 来查找附近的用户。 我现在已经被困了两天了。 我搜索了 Google 和 Whosebug 并尝试了我在那里找到的所有内容但没有任何成功。现在我最后的希望就是自己创建这个帖子,希望有人能帮助我。

我的数据库大致如下所示:

users
    user_id1
        email: xxx@gmail.com
        username: xxx
    user_id2
        email: yyy@gmail.com
        username: yyy
users_locations
    user_id1
        location
            g: xxxx
            l
                0: 30.0000
                1: 5.0000
    user_id2
        location
            g: yyyy
            l
                0: 30.0010
                1: 5.0010

我不知道是否有必要将位置数据与用户分开保存,但我也尝试过这样保存,结果相同,所以我认为这无关紧要:

users
    user_id1
        email: xxx@gmail.com
        username: xxx
        location
            g: xxx
            l
                0: 30.0000
                1: 5.0000

现在我使用的代码:

为了将位置写入数据库,我使用以下方法,工作正常:

let user = FIRAuth.auth()?.currentUser
let uid = user?.uid

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_locations")
let geoFire = GeoFire(firebaseRef: geofireRef.child(uid!))

geoFire?.setLocation(myLocation, forKey: "location")

现在,我尝试使用 GeoFire 查询向我显示定义半径内的所有用户,该半径没有打印任何内容:

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_location")
let geoFire = GeoFire(firebaseRef: geofireRef)

let circleQuery = geoFire?.query(at: center, withRadius: 10)
circleQuery?.observe(.keyEntered, with: { (key: String?, location: CLLocation?) in
         print("Key '\(key!)' entered the search are and is at location '\(location!)'")
    })

我发现如果我转到我的实际 uid child,我会得到一个结果。然后它会打印我的实际用户位置和密钥,但这当然不是我想要的。

let geoFire = GeoFire(firebaseRef: geofireRef.child(uid!))

所以我希望 GeoFire 搜索我在 'users_locations' 中的 uid 和 return 我定义半径内的所有 uid。

对我来说,它似乎只是在我的参考文献中定义的 child 中搜索名为 'location' 的 child (users_location -> user_uid) 如果我尝试查询 'users_location',我什么也得不到。

我做错了什么? 如何使查询搜索引用 child 并将 uid 还给我?

试试像这样用 GeoFire 写位置。您不需要将它们存储在 location 键下。

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_locations")
let geoFire = GeoFire(firebaseRef: geofireRef)

geoFire?.setLocation(myLocation, forKey: uid!)

使用 Geofire 时,您有两个数据列表:

  1. 对象列表,在您的例子中是用户
  2. 这些对象的位置列表,通过 Geofire 进行维护和查询

这两个列表确实是分开的。来自 Geofire documentation(强调我的):

Assume you are building an app to rate bars and you store all information for a bar, e.g. name, business hours and price range, at /bars/<bar-id>. Later, you want to add the possibility for users to search for bars in their vicinity. This is where GeoFire comes in.

You can store the location for each bar using GeoFire, using the bar IDs as GeoFire keys. GeoFire then allows you to easily query which bar IDs (the keys) are nearby. To display any additional information about the bars, you can load the information for each bar returned by the query at /bars/<bar-id>.

我针对您的问题突出显示了两个最重要的部分:

  1. 用户列表中的项目和他们的位置列表中的项目应该使用相同的键(这是安德鲁在他的回答中也指出的)。通过使用相同的密钥,您可以轻松地查找用户的位置,反之亦然。
  2. 您需要为查询中的每个键单独加载用户。

Andrew 展示了如何为每个用户正确编写位置。剩下的就是加载关于结果范围内每个用户的附加信息。你会在他 .keyEntered 处理程序中执行此操作:

let usersRef = ref.child("users")

let circleQuery = geoFire?.query(at: center, withRadius: 10)
circleQuery?.observe(.keyEntered, with: { (key: String?, location: CLLocation?) in

     print("Key '\(key!)' entered the search are and is at location '\(location!)'")
     // Load the user for the key
     let userRef = usersRef.child(key)
     userRef.observeSingleEvent(FIRDataEventType.value, with: { (snapshot) in
         let userDict = snapshot.value as? [String : AnyObject] ?? [:]
         // ...
     })
})