[英]Fetching data really fast from Google cloud firestore
我正在制作一個 flutter 應用程序,我正在使用 cloud firestore 作為我的在線數據庫。 我的應用程序中的一項功能是尋找附近的用戶並在屏幕上的自定義小部件中向當前用戶顯示他們的個人資料。 我這樣做的方法是獲取當前用戶的位置(實時位置或保存在數據庫中的地址),然后為用戶檢查數據庫集合中的每個用戶。 我從存儲的數據中獲取用戶的地址,使用距離矩陣 API 計算距離,然后如果距離小於特定數字(例如 10000 米),我會為用戶創建配置文件小部件以在屏幕上顯示它。
有2個問題:
1-如果我的用戶數量增加(例如一百萬用戶),通過查看每個用戶詳細信息並計算距離,在屏幕上獲得結果可能需要很長時間。 目前,我只有 20 個用戶用於測試目的,當我搜索附近的用戶時,結果可能需要 30 秒才能顯示在屏幕上。
2- 在互聯網連接速度較慢的情況下,等待時間可能會更長,並且它可以使用大量用戶數據來完成這項簡單的任務。
如何改進此功能並使其更快?
(我目前的想法是將用戶的位置划分到不同的文檔中,然后使用當前用戶的位置僅瀏覽其中一個文檔。問題是如何有效地划分地址並找到最佳地址為了。)
下面是我找到附近用戶並將他們添加到我傳遞給我的自定義小部件類的列表中的代碼。
final List<UserBoxDesign> listOfBoxes = [];
final FirebaseUser currentUser = await auth.currentUser();
final String currentUserId = currentUser.uid;
if (_userLocationSwitchValue == false) { //use default address of the user
currentUserAddress = await _databaseManagement.getUserCollectionValues(
currentUserId, "address");
} else {
//currentUserAddress = //to do, get device location here.
}
if (_searchValue == SearchValues.Users) {
final List<String> userIds = await _databaseManagement.getUserIds();
for (String id in userIds) {
final String otherUserLocations =
await _databaseManagement.getUserCollectionValues(id, "address");
final String distanceMeters = await _findDistanceGoogleMaps(
currentUserAddress, otherUserLocations);
if (distanceMeters == "Address can't be calculated" ||
distanceMeters == "Distance is more than required by user") {
//if it's not possible to calculate the address then just don't do anything with that.
} else {
final double distanceValueInKilometers = (double.parse(
distanceMeters) /
1000)
.roundToDouble();
final String userProfileImageUrl =
await _databaseManagement.getUserCollectionValues(id, "image");
final String username =
await _databaseManagement.getUserCollectionValues(id, "username");
listOfBoxes.add(
UserBoxDesign( //it creates a custom widget for user if user is nearby
userImageUrl: userProfileImageUrl,
distanceFromUser: distanceValueInKilometers,
userId: id,
username: username,
),
); //here we store the latest values inside the reserved data so when we create the page again, the value will be the reservedData value which is not empty anymore
}
print(listOfBoxes);
}
listOfBoxes.sort((itemA,itemB)=>itemA.distanceFromUser.compareTo(itemB.distanceFromUser)); //SORTs the items from closer to more far from user (we can reverse it to far comes first and close goes last)
setState(() {
_isSearchingForUser = false;
});
return listOfBoxes;
這是我計算起始地址和目標地址之間距離的代碼。
Future<String> _findDistanceGoogleMaps(
String originAddress, String destinationAddress) async {
final String url =
"https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=$originAddress&destinations=$destinationAddress&key=$GoogleMapsAPIKey";
try {
final response = await http.get(url);
final responseDecoded = json.decode(response.body);
final distanceInMeters = double.parse(responseDecoded["rows"][0]
["elements"][0]["distance"]["value"]
.toString()); //this is the value in meters always so for km , divide by 1000.
if (distanceInMeters < 100000) {
return distanceInMeters.toString();
} else {
return "Distance is more than required by user";
}
} catch (e) {
return "Address can't be calculated";
}
}
如果您給出代碼示例,則很容易回答。 我可以建議(我們有類似的任務)使用坐標經度和緯度並在您的范圍內提出請求。
所以你不需要距離矩陣 API(我認為它會很昂貴)並且你的查詢將快速而便宜。
我用谷歌搜索並在這里找到了答案如何使用 firestore 運行地理“附近”查詢?
==更新問題后==
您嘗試使用 screen 內的所有邏輯並同步執行。 正因為如此,你有這么長的渲染時間。 您計算用戶設備上的所有內容並傳遞給小部件return listOfBoxes;
相反,您可以嘗試使用 Streambuilder,示例在此處如何在 flutter 中有效訪問 firestore 引用字段的數據?
以這樣的方式組織數據庫中的數據,您可以根據自己的目的提出請求: "Find all users within X range sorted by distance AND ..."
。 在這種情況下,Firebase 會非常快速地完成並將數據異步傳遞給您的 Streambuilder。 我猜你可以保留經度、緯度並使用它們而不是地址。
抱歉,我無法重寫您的代碼,信息不足。 只需通過鏈接查看示例,就有一個很好的示例。
==更新2==
包https://pub.dev/packages/geoflutterfire允許將地理數據存儲到 Firestore 以及如何發出請求
// Create a geoFirePoint
GeoFirePoint center = geo.point(latitude: 12.960632, longitude: 77.641603);
// get the collection reference or query
var collectionReference = _firestore.collection('locations');
double radius = 50;
String field = 'position';
Stream<List<DocumentSnapshot>> stream = geo.collection(collectionRef: collectionReference)
.within(center: center, radius: radius, field: field);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.