【问题标题】:Firestore geoquery on nested firestore collection嵌套 Firestore 集合上的 Firestore 地理查询
【发布时间】:2022-01-12 14:22:46
【问题描述】:

按照教程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()+"");
                }
            });
}

【问题讨论】:

    标签: android firebase google-maps google-cloud-firestore


    【解决方案1】:

    这个查询永远不会返回任何结果:

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-18
      • 2019-06-20
      • 2021-09-29
      • 2018-10-16
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 2021-05-29
      相关资源
      最近更新 更多