firebase 如何根据用户/最近的geohash的位置对firestore db中的数据进行排序?

lf3rwulv  于 2023-08-07  发布在  其他
关注(0)|答案(2)|浏览(98)

我有一个用React Native和Firebase编写的应用程序,我在db中有一个客户端列表,其中有他们的geohash,现在我需要向用户显示我的客户端列表,从最近到最远排序。在文档示例中,它说

const q = db.collection('cities')
      .orderBy('geohash')
      .startAt(b[0])
      .endAt(b[1]);

字符串
但是问题是在我的firebase对象上没有.collection,我这样示例化它

import { initializeApp } from "firebase/app";
import { Firestore, getFirestore } from "firebase/firestore";
import Constants from "expo-constants";

let firestore;
if (Constants.manifest?.extra) {
  const {
    FIREBASE_API_KEY,
    FIREBASE_APP_ID,
    FIREBASE_AUTH_DOMAIN,
    FIREBASE_MESSAGING_SENDER_ID,
    FIREBASE_PROJECT_ID,
    FIREBASE_STORAGE_BUCKET,
  } = Constants.manifest.extra;

  const firebaseConfig = {
    apiKey: FIREBASE_API_KEY,
    authDomain: FIREBASE_AUTH_DOMAIN,
    projectId: FIREBASE_PROJECT_ID,
    storageBucket: FIREBASE_STORAGE_BUCKET,
    messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,
    appId: FIREBASE_APP_ID,
  };

  const app = initializeApp(firebaseConfig);
  firestore = getFirestore();
}
export default firestore as Firestore;


在本例中,Firebase数据库的示例化方式如下

db = firebase.firestore(app);


但没有要从“firebase/firestore”导入的firebase对象
我如何按用户的位置对数据库中的数据进行排序?

  • 谢谢-谢谢
mo49yndu

mo49yndu1#

您开始使用的示例代码使用Firebase SDK版本8及更低版本的命名空间语法。但是,您的代码正在导入Firebase SDK版本9或更高版本,这些版本使用新的模块化语法。
如果我们使用这个v8代码:

const q = db.collection('cities')
  .orderBy('geohash')
  .startAt(b[0])
  .endAt(b[1]);

字符串
v9中的等价物是:

import { collection, query, orderBy, startAt, endAt } from "firebase/firestore";
...
const q = query(collection(q, 'cities'), 
  orderBy('geohash'),
  startAt(b[0]),
  endAt(b[1])
);


我通常会将Firebase文档放在方便的位置,例如,ordering and limiting data部分包含了v8和v9语法并排的示例。阅读v9 upgrade guide也总是一个好主意。
更新(2023-07-19):performing geoqueries on Firestore的文档刚刚更新,包含了模块化语法的代码示例。

ss2ws0br

ss2ws0br2#

让我们把问题分解如下:

**1.为每个客户端文档保存geohash *

假设我们有一个clients集合,包含如下文档:

{
"hy_uyttdhh":{
firstName:"Satya",
lastName:"Nadella",
geohash:"gbsuv7zt",
coordinate:{
lat:48.669,
lng:-4.32913}
}},
"90kuxddgty":{
firstName:"Sundar",
lastName:"Pichai",
geohash:"gbsuv7z",
coordinate:{
lat:47.669,
lng:-4.70913}
}
},
"iutybdfertyu":{
firstName:"Parag",
lastName:"Agrawal",
geohash:"gbsuv7zs",
coordinate:{
lat:47.669,
lng:-4.70913}
}
}
}

字符串

2.只获取客户端附近用户的位置

有两个因素可以确定客户端是否是附近的用户:

  • 用户当前位置坐标
  • 以英里或公里为单位的边界半径,我们预计客户在附近

考虑到这一点,让我们编写一个函数,只在指定的边界内匹配和返回客户端。

// Utility library by Firebase team to work with Geolocation
const geofire = require("geofire-common");

const getNearbyClients = async () => {
  const boundaryRadius = 1; // km
  // Reference to clients collection - Syntax should change if you're using Firebase  V9
  const clientsRef = firebase.firestore.collection("clients");
  // Current user location - mocked for sake of simplicity
  const coordinates = { latitude: "48.669", longitude: "-4.32913" };

  const center = [coordinates.latitude, coordinates.longitude];
  const radiusInM = radius * 1000;

  // Generate geohash boundaries based on center radius, In our context, this will based on current users coordinates
  const bounds = geofire.geohashQueryBounds(center, radiusInM);
  // Each item in 'bounds' represents a startAt/endAt pair. We have to issue
  // a separate query for each pair. There can be up to 9 pairs of bounds
  // depending on the overlap, but in most cases, there are 4.

  const matchedBoundariesPromises = bounds.map((b) => {
    let query = clientsRef.orderBy("geohash").startAt(b[0]).endAt(b[1]);
    query = query.get();
    return query;
  });

  // Collect all the query results together into a single list
  const snapshots = await Promise.all(promises);
  let matchingDocs = [];
  snapshots.forEach((snap) => {
    snap.docs.forEach((doc) => {
      if (doc.data()) {
        matchingDocs.push(doc.data());
      }
    });
  });
  return matchingDocs;
};

3.匹配到的客户端按用户最近排序

与附近的客户从firestore,我们可以排序最近的与此功能

const sortClientsByNearest = (clients = [])=>{

// Current user location - mocked for sake of simplicity
 const coordinates = { latitude: "48.669", longitude: "-4.32913" };

 const center = [coordinates.latitude, coordinates.longitude];
 
const  distanceInKm  =  geofire.distanceBetween([lat,  lng],  center);

return  [...clients].sort(function  (a,  b)  {
const distanceFromA =  geofire.distanceBetween([a.coordinate.lat,  a.coordinate.lng],  center)  
const distanceFromB =  geofire.distanceBetween([b.coordinate.lat,  b.coordinate.lng],  center

return  distanceFromA - distanceFromB

});

}

相关问题