Firebase位置查询

时间:2016-10-26 21:09:00

标签: android firebase location firebase-realtime-database

我正在使用firebase在android上设计一个基于位置的餐厅搜索应用程序。在firebase上的餐厅类如下;

 restaurants
-key
  address: "NYC"
  city: "New York"
  description: ""
  id: 60000
  latitude: 39.895107
  longitude: 32.797819
  name: "Pizza Store"

片段类

mainActivity.mDatabase.child("restaurants").addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            System.out.println("There are " + snapshot.getChildrenCount() + " restaurans");
            for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                Restaurant post = postSnapshot.getValue(Restaurant.class);
                mapmap2.put(post.getName(), postSnapshot.getKey());
                restaurants.add(post);
            }
            adapter = new RestaurantCardViewAdapter(getActivity(), restaurants, MapListFragment.this);
            mRecyclerView.setAdapter(adapter);
        }

        @Override
        public void onCancelled(DatabaseError firebaseError) {
            System.out.println("The read failed: " + firebaseError.getMessage());
        }
    });

现在,我可以列出所有的餐馆。但我想查询用户位置。首先,我想在用户位置附近列出20家餐馆,当用户加载页面时,我希望获得下一个20家最近的餐馆。我在网上搜索一下。我找到了GeoFire库,但据我所知它使用的是firebase的旧版本。我如何查询这些标准?

2 个答案:

答案 0 :(得分:3)

Firebase查询只能按单个属性进行过滤/排序。由于位置包含经度和纬度,您现在使用的格式不能根据位置进行查询。

幸运的是,有一个名为GeoFire的附加库。该库将经度和纬度合并为一个名为geohash的属性。根据此属性,它可以按距离过滤到给定位置。

我建议您查看Geofire并查看它是否适合您的用例。

答案 1 :(得分:2)

我在答案的帮助下解决了这个问题。我为一个名为“restaurant_locations”的geofire推了一个单独的孩子。当我插入餐馆时,我会单独推送这些位置。

      GeoFire geoFire;
      String itemId = mDatabase.child("restaurants").push().getKey();
      mDatabase.child("restaurants").child(itemId).setValue(restaurant);

      geoFire = new GeoFire(mDatabase.child("restaurants_location"));
      geoFire.setLocation(itemId, new GeoLocation(Double.valueOf(rd.location.latitude), Double.valueOf(rd.location.longitude)));

然后,当我需要查询位置时,我使用了geofire查询。

    geoFire = new GeoFire(mDatabase.child("restaurants_location"));
    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(39.896263, 32.799652), 1);

    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {
            System.out.println(String.format("Key %s entered the search area at [%f,%f]", key, location.latitude, location.longitude));
            mDatabase.child("restaurants").child(key).addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot snapshot) {
                    Restaurant res= snapshot.getValue(Restaurant.class);
                }
                @Override
                public void onCancelled(DatabaseError firebaseError) {
                    System.out.println("The read failed: " + firebaseError.getMessage());
                }

                // ...
            });
        }

        @Override
        public void onKeyExited(String key) {
            System.out.println(String.format("Key %s is no longer in the search area", key));
        }

        @Override
        public void onKeyMoved(String key, GeoLocation location) {
            System.out.println(String.format("Key %s moved within the search area to [%f,%f]", key, location.latitude, location.longitude));
        }

        @Override
        public void onGeoQueryReady() {
            System.out.println("All initial data has been loaded and events have been fired!");
        }

        @Override
        public void onGeoQueryError(DatabaseError error) {
            System.err.println("There was an error with this query: " + error);
        }
    });

但我仍然担心这是从数据库获取餐馆的最有效方式,因为我单独为“餐馆”根上的每个餐馆密钥运行查询。有没有人知道更有效的方式请告诉我们。