const [location, setLocation] = useState<any>()
const userId = '1234'
const updateUserLocation = async (position: any) => {
const { latitude, longitude } = position.coords
await database()
.ref(`usersLocations/${userId}`)
.set(encodeLocationObject({ latitude, longitude }))
console.log('location updated')
}
useEffect(() => {
let watchId: number
const handleLocationChange = async (position: any) => {
setLocation(position)
await updateUserLocation(position)
setTimeout(async () => {
const nearbyUsers = await findNearbyUsers(position)
console.log(nearbyUsers)
}, 5000)
}
const startWatchingLocation = async () => {
watchId = Geolocation.watchPosition(
handleLocationChange,
error => {
Alert.alert(`Error getting location: ${error.message}`)
},
{
enableHighAccuracy: true,
distanceFilter: 10,
},
)
}
startWatchingLocation()
return () => {
Geolocation.clearWatch(watchId)
}
}, [])
export const findNearbyUsers = async (userLocation: GeoPosition) => {
try {
const {latitude, longitude} = userLocation.coords
const geohash = ngeohash.encode(latitude, longitude)
const RADIUS = USER_DISCOVER_RANGE + 50
const center = ngeohash.decode(geohash)
const latPerMeter = 1 / 111111
const lonPerMeter = Math.abs(Math.cos(center.latitude) * latPerMeter)
const latMin = center.latitude - latPerMeter * RADIUS
const latMax = center.latitude + latPerMeter * RADIUS
const lonMin = center.longitude - lonPerMeter * RADIUS
const lonMax = center.longitude + lonPerMeter * RADIUS
const dbRef = database()
.ref('usersLocations')
.orderByChild('g')
.startAt(ngeohash.encode(latMin, lonMin))
.endAt(ngeohash.encode(latMax, lonMax))
const users = (await dbRef.once('value')).val()
const currentUserID = '123'
let nearbyUsers: Array<suggestedUser> = []
console.log(Object.keys(users));
for (let userID of Object.keys(users)) {
if (userID !== currentUserID) {
const otherLocation = users[userID].l
// console.log({latitude, longitude}, otherLocation)
const distance = getDistance({latitude, longitude}, otherLocation)
console.log(userID, distance);
if (distance < 100) {
nearbyUsers.push({distance, id: userID})
}
}
}
// console.log('user range', USER_DISCOVER_RANGE)
// if (users) {
// Object.keys(users).forEach(userID => {})
// }
dbRef.off('value')
return nearbyUsers
} catch (error) {
console.error(error)
throw error
}
}
我在我的React Native应用程序中有这样的代码,它设置用户位置并查询附近的用户。问题是,当查询时,它第一次返回的数据不一致,它返回的数据少于它应该返回的数据,下一次它返回正确的结果后。
我尝试了geofire-js,但由于它不适用于'@react-native-firebase/database',由于大量的读取/写入,我也不能使用Firestore。
1条答案
按热度按时间1zmg4dgp1#
你在这里采取的方法不会起作用:
虽然彼此相似的geohash值可以保证彼此接近,但反之则不然:不能保证彼此接近的点将具有相似的Geohash值。
看看这个范围,例如:
虽然
9r0
、9r1
、9r2
和9r3
在地理位置和字母顺序上都很接近,但9pp
在地理位置上也很接近,但不是字母顺序。因此,您需要为单个地理查询查询多个范围的geohash,最多9个iirc,但通常介于4和6之间。这就是为什么GeoFire库返回geohash边界列表的原因,您也可以在此代码片段中看到:https://firebase.google.com/docs/firestore/solutions/geoqueries#web_2
我的建议是查看geofire-common库的
geohashQueryBounds
函数,并从中复制您需要的内容。