2016-10-26 5 views
1

나는 firebase로 안드로이드 기반의 위치 기반 레스토랑 검색 응용 프로그램을 디자인하고 있습니다. firebase에 다음과 같은 레스토랑 클래스;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로 작업하는 것을 이해합니다. 이러한 기준으로 어떻게 쿼리 할 수 ​​있습니까?

답변

0

Firebase 쿼리는 단일 속성으로 만 필터링/정렬 할 수 있습니다. 위치는 경도와 위도로 구성되어 있으므로 현재 가지고있는 형식으로 위치를 기준으로 쿼리 할 수 ​​없습니다.

운 좋게도 GeoFire이라는 추가 기능 라이브러리가 있습니다. 이 라이브러리는 경도와 위도를 geohash이라는 단일 속성으로 결합합니다. 이 속성을 기반으로 특정 위치까지 거리별로 필터링 할 수 있습니다.

Geofire를 확인하고 사용 사례에 적합한 지 확인하는 것이 좋습니다.

+0

대단히 감사합니다. GeoFire의 속성을 검색합니다. 하지만 몇 가지 의구심이 있습니다. 위치 항목을 레스토랑에서 분리하여 보관하는 것이 좋습니다. 같은 위치 루트에 레스토랑 ID와 검색어가있는 위치 정보를 입력합니다. 이 링크와 마찬가지로 http://stackoverflow.com/questions/38340949/how-to-save-geofire-coordinates-along-with-other-items-in-firebase-database. 그러나 나는 그 위치를 묻는다면 가장 가까운 레스토랑 키를 얻을 것이라고 이해하지 못합니다. 그 후에, 나는이 열쇠들로이 식당을 찾아야 해. 어떻게해야할까요, 값 비싼 데이터베이스가 아닌가요? – starrystar

1

답변의 도움으로 문제를 해결했습니다. 나는 "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); 
     } 
    }); 

하지만 난 여전히 내가 "레스토랑"루트에있는 모든 단일 레스토랑 키를 쿼리 별도로 실행되기 때문에 즉, 데이터베이스에서 식당을 얻을 수있는 가장 효율적인 방법이 있습니다에 대해 우려하고있다. 더 효율적인 방법을 아는 사람이 있는지 알려주세요.

+0

그래, 해답을 얻는 것이 가장 효율적인 방법 일 것입니다. Frank van Puffelen ... 감사합니다 ^^ –