Как сохранить координаты GeoFire вместе с другими элементами в базе данных Firebase?

Я разрабатываю приложение и сохраняю некоторые строки, такие как postedAtTime, postedBy, postedOnDate в базе данных Firebase. Я хочу сохранить координаты GeoFire в том же node, в котором сохранена вся указанная выше строка, так что позже я могу сделать запрос легко.

Здесь путь, к которому я сохраняю все строки:

databaseReferenceHRequests = firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/");

Вот как я его сохраняю:

// in onButtonClicked method:
postNewRequest(null, imageUID, MainActivity.userName.getText().toString(), time, date, utcFormatDateTime, MainActivity.userEmail.getText().toString(), geoFire);

// the method:
public void postNewRequest(Bitmap bitmap, String imageUIDh, String postedBy, String postedAtTime, String postedOnDate, String utcFormatDateTime, String userEmail, GeoFire geoFire) {
    HRequest hRequest = new HelpRequest(null, imageUIDh, postedBy, postedAtTime, postedOnDate, utcFormatDateTime, userEmail, geoFire);
    databaseReferenceHRequests.push().setValue(hRequest);
}

Вот как он сохраняется в базе данных:

скриншот структуры базы данных

Я хочу сохранить координаты GeoFire в том же node, что здесь -KLIoLUsI0SpQZGpV1h4. Это просто идентификатор push, и он генерируется случайным образом.

Я попробовал это, указав эту ссылку:

geoFire = new GeoFire(firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/"));

И затем нажав его на другие элементы, как показано выше. Но это сохранили только координаты GeoFire, а не другие элементы под node requests.

Итак, какова должна быть моя ссылка GeoFire, чтобы она сохранялась вместе со всеми данными в том же node?

Что здесь происходит? Пожалуйста, дайте мне знать.

Ответ 1

Ответ Фрэнка верный, но я хочу привести пример. Структура вашей базы данных должна быть такой.

"items" : {
    <itemId> : {
        "someData" : "someData",
        ...
    }
}
"items_location" : {
    <itemId> : {
        <geofireData> ...
    }
}

Чтобы получить данные, сначала вам нужно выполнить GeoQuery в items_location node, а затем получить данные по методу onKeyEntered. Параметр key является itemId из моего примера.

geoFire = new GeoFire(FirebaseDatabase.getInstance().getReference().child("items_location");
geoQuery = geoFire.queryAtLocation(geoLocation), radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
         //retrieve data
    }
};    

Надеюсь, что это поможет.

ИЗМЕНИТЬ Как нажимать элемент и задавать геологические данные.

String itemId = ref.child("items").push().getKey();

ref.child("items").child(itemId).setValue(item);

geoFire = new GeoFire(ref.child("items_location"));
geoFire.setLocation(itemId, new GeoLocation(lattitude, longitude));

РЕДАКТИРОВАТЬ Сохранить данные и данные геоданных в одном вызове API

GeoHash geoHash = new GeoHash(new GeoLocation(latitude, longitude));
Map<String, Object> updates = new HashMap<>();
updates.put("items/" + itemId, item);
updates.put("items_location/" + itemId + "/g", geoHash.getGeoHashString());
updates.put("items_location/" + itemId + "/l", Arrays.asList(latitude, longitude));
ref.updateChildren(updates);

Ответ 2

Когда вы используете Geofire, у вас есть два списка данных:

  • список элементов с их регулярными свойствами
  • список индексов geohash и связанных с ними ключей, которые вы запрашиваете через Geofire

Вы используете ключи для получения результатов из Geoquery для обычных элементов. Поэтому события для Geofire называются "Key Entered", "Key Exited" и т.д.

Попытка сохранить их в одном node является плохой идеей, поскольку вы смешиваете в основном статические данные (свойства ваших элементов) с сильно изменчивыми данными (информация о геолокации). Разделение двух сторон приводит к повышению производительности, поэтому Geofire обеспечивает его выполнение.

Хотя могут быть случаи использования, когда свойства и геоданные одинаково динамичны/статичны, GeoFire не поддерживает сохранение геоданных и других свойств в одном месте.

Ответ 3

Вы можете использовать функции Firebase для ввода его для каждой новой записи

let functions = require('firebase-functions');

let GeoFire = require('geofire');

exports.testLocation = functions.database.ref('/items/{item}').onWrite(event => {
let data = event.data.val();
   console.log(data);
   console.log(event.params.item);

   if (data.location && data.location.coords) {

       console.log('Update GeoFire');

       let ref = event.data.adminRef.parent.parent.child('/items_locations'));

       let key = event.params.test;
       let location = [data.location.coords.latitude, data.location.coords.longitude]);
       let geoFire = new GeoFire(ref);

       geoFire.set(key, location).then(() => {
          console.log('Update succesfull');
       }).catch(error => {
          console.log(error);
       });
    }
}