嵌套 Firestore 集合上的 Firestore 地理查询
Firestore geoquery on nested firestore collection
学习教程https://firebase.google.com/docs/firestore/solutions/geoqueries
https://www.youtube.com/watch?v=mx1mMdHBi5Q 我创建了我的数据库设计,看起来像
当我查询任何位置时,我总是得到 0 个结果,然后我尝试查询非嵌套集合(如教程视频 https://www.youtube.com/watch?v=mx1mMdHBi5Q 中所示),然后我得到了结果。
我的非嵌套集合设计如下:
嵌套集合的代码(这是我的要求,但不起作用)
public void queryHashes() {
// Find cities within 50km of London
final GeoLocation center = new GeoLocation(19.912524, 76.079626);
final double radiusInM = 50 * 1000;
// 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 overlap, but in most cases there are 4.
List<GeoQueryBounds> bounds = GeoFireUtils.getGeoHashQueryBounds(center, radiusInM);
final List<Task<QuerySnapshot>> tasks = new ArrayList<>();
for (GeoQueryBounds b : bounds) {
Query q = db.collection("Owners").document().collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
tasks.add(q.get());
}
// Collect all the query results together into a single list
Tasks.whenAllComplete(tasks)
.addOnCompleteListener(new OnCompleteListener<List<Task<?>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<?>>> t) {
List<DocumentSnapshot> matchingDocs = new ArrayList<>();
for (Task<QuerySnapshot> task : tasks) {
QuerySnapshot snap = task.getResult();
for (DocumentSnapshot doc : snap.getDocuments()) {
double lat = doc.getDouble("lat");
double lng = doc.getDouble("lng");
// We have to filter out a few false positives due to GeoHash
// accuracy, but most will match
GeoLocation docLocation = new GeoLocation(lat, lng);
double distanceInM = GeoFireUtils.getDistanceBetween(docLocation, center);
if (distanceInM <= radiusInM) {
matchingDocs.add(doc);
}
}
}
// matchingDocs contains the results
// ...
Log.v("matchingDocsD", matchingDocs.size()+"");
}
});
}
非嵌套集合代码(有效)
public void queryHashes() {
// Find cities within 50km of London
final GeoLocation center = new GeoLocation(19.912524, 76.079626);
final double radiusInM = 50 * 1000;
// 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 overlap, but in most cases there are 4.
List<GeoQueryBounds> bounds = GeoFireUtils.getGeoHashQueryBounds(center, radiusInM);
final List<Task<QuerySnapshot>> tasks = new ArrayList<>();
for (GeoQueryBounds b : bounds) {
Query q = db.collection("10K")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
tasks.add(q.get());
}
// Collect all the query results together into a single list
Tasks.whenAllComplete(tasks)
.addOnCompleteListener(new OnCompleteListener<List<Task<?>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<?>>> t) {
List<DocumentSnapshot> matchingDocs = new ArrayList<>();
for (Task<QuerySnapshot> task : tasks) {
QuerySnapshot snap = task.getResult();
for (DocumentSnapshot doc : snap.getDocuments()) {
double lat = doc.getDouble("lat");
double lng = doc.getDouble("lng");
// We have to filter out a few false positives due to GeoHash
// accuracy, but most will match
GeoLocation docLocation = new GeoLocation(lat, lng);
double distanceInM = GeoFireUtils.getDistanceBetween(docLocation, center);
if (distanceInM <= radiusInM) {
matchingDocs.add(doc);
}
}
}
// matchingDocs contains the results
// ...
Log.v("matchingDocsD", matchingDocs.size()+"");
}
});
}
此查询永远不会 return 任何结果:
Query q = db.collection("Owners").document().collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
当您在不带任何参数的情况下调用 document()
时,您正在创建对新的、不存在的文档 的引用。所以它的 Ghars
子集合也不存在,你的查询也得不到结果。
如果您想查询特定所有者的 Ghars
子集合,您应该在调用 document()
:
时指定所有者的文档 ID
//
Query q = db.collection("Owners").document(ownerDocId).collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
如果您想查询所有 Ghars
个子集合,您可以 use a collection group query,它会查询具有特定名称的所有集合:
//
Query q = db.collectionGroup("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
学习教程https://firebase.google.com/docs/firestore/solutions/geoqueries https://www.youtube.com/watch?v=mx1mMdHBi5Q 我创建了我的数据库设计,看起来像
当我查询任何位置时,我总是得到 0 个结果,然后我尝试查询非嵌套集合(如教程视频 https://www.youtube.com/watch?v=mx1mMdHBi5Q 中所示),然后我得到了结果。
我的非嵌套集合设计如下:
嵌套集合的代码(这是我的要求,但不起作用)
public void queryHashes() {
// Find cities within 50km of London
final GeoLocation center = new GeoLocation(19.912524, 76.079626);
final double radiusInM = 50 * 1000;
// 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 overlap, but in most cases there are 4.
List<GeoQueryBounds> bounds = GeoFireUtils.getGeoHashQueryBounds(center, radiusInM);
final List<Task<QuerySnapshot>> tasks = new ArrayList<>();
for (GeoQueryBounds b : bounds) {
Query q = db.collection("Owners").document().collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
tasks.add(q.get());
}
// Collect all the query results together into a single list
Tasks.whenAllComplete(tasks)
.addOnCompleteListener(new OnCompleteListener<List<Task<?>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<?>>> t) {
List<DocumentSnapshot> matchingDocs = new ArrayList<>();
for (Task<QuerySnapshot> task : tasks) {
QuerySnapshot snap = task.getResult();
for (DocumentSnapshot doc : snap.getDocuments()) {
double lat = doc.getDouble("lat");
double lng = doc.getDouble("lng");
// We have to filter out a few false positives due to GeoHash
// accuracy, but most will match
GeoLocation docLocation = new GeoLocation(lat, lng);
double distanceInM = GeoFireUtils.getDistanceBetween(docLocation, center);
if (distanceInM <= radiusInM) {
matchingDocs.add(doc);
}
}
}
// matchingDocs contains the results
// ...
Log.v("matchingDocsD", matchingDocs.size()+"");
}
});
}
非嵌套集合代码(有效)
public void queryHashes() {
// Find cities within 50km of London
final GeoLocation center = new GeoLocation(19.912524, 76.079626);
final double radiusInM = 50 * 1000;
// 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 overlap, but in most cases there are 4.
List<GeoQueryBounds> bounds = GeoFireUtils.getGeoHashQueryBounds(center, radiusInM);
final List<Task<QuerySnapshot>> tasks = new ArrayList<>();
for (GeoQueryBounds b : bounds) {
Query q = db.collection("10K")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
tasks.add(q.get());
}
// Collect all the query results together into a single list
Tasks.whenAllComplete(tasks)
.addOnCompleteListener(new OnCompleteListener<List<Task<?>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<?>>> t) {
List<DocumentSnapshot> matchingDocs = new ArrayList<>();
for (Task<QuerySnapshot> task : tasks) {
QuerySnapshot snap = task.getResult();
for (DocumentSnapshot doc : snap.getDocuments()) {
double lat = doc.getDouble("lat");
double lng = doc.getDouble("lng");
// We have to filter out a few false positives due to GeoHash
// accuracy, but most will match
GeoLocation docLocation = new GeoLocation(lat, lng);
double distanceInM = GeoFireUtils.getDistanceBetween(docLocation, center);
if (distanceInM <= radiusInM) {
matchingDocs.add(doc);
}
}
}
// matchingDocs contains the results
// ...
Log.v("matchingDocsD", matchingDocs.size()+"");
}
});
}
此查询永远不会 return 任何结果:
Query q = db.collection("Owners").document().collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
当您在不带任何参数的情况下调用 document()
时,您正在创建对新的、不存在的文档 的引用。所以它的 Ghars
子集合也不存在,你的查询也得不到结果。
如果您想查询特定所有者的 Ghars
子集合,您应该在调用 document()
:
//
Query q = db.collection("Owners").document(ownerDocId).collection("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);
如果您想查询所有 Ghars
个子集合,您可以 use a collection group query,它会查询具有特定名称的所有集合:
//
Query q = db.collectionGroup("Ghars")
.orderBy("geohash")
.startAt(b.startHash)
.endAt(b.endHash);