Как сохранить координаты GeoFire вместе с другими элементами в базе данных Firebase?
Я разрабатываю приложение и сохраняю некоторые строки, такие как postedAtTime
, postedBy
, postedOnDate
в базе данных Firebase. Я хочу сохранить координаты GeoFire в том же узле, в котором сохранены все приведенные выше строки, чтобы позже я мог легко выполнить запрос.
Вот путь, по которому я сохраняю все строки:
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 в том же узле, который -KLIoLUsI0SpQZGpV1h4
Вот. Это просто идентификатор push, и он генерируется случайным образом.
Я попробовал это, дав следующую ссылку:
geoFire = new GeoFire(firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/"));
А затем подтолкнуть его с другими предметами, как показано выше. Но это сохранило только координаты GeoFire, а не другие элементы под узлом requests
,
Итак, какой должна быть моя ссылка GeoFire, чтобы она сохранялась вместе со всеми данными в одном узле?
Что здесь не так? Пожалуйста, дайте мне знать.
4 ответа
Ответ Фрэнка правильный, но я хочу привести пример. Ваша структура базы данных должна быть такой.
{
"items" : {
<itemId> : {
"someData" : "someData",
...
}
},
"items_location" : {
<itemId> : {
<geofireData> ...
}
}
}
Чтобы получить данные, сначала вам нужно сделать GeoQuery на items_location
узел, а затем получить данные на 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
}
};
Надеюсь это поможет.
РЕДАКТИРОВАТЬ Как нажать элемент и установить данные Geofire.
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);
Когда вы используете Geofire, у вас есть два списка данных:
- список предметов с их обычными свойствами
- список индексов геохэш и их связанных ключей, которые вы запрашиваете через Geofire
Вы используете ключи для перехода от результатов Geoquery к обычным элементам. Вот почему события для Geofire называются "Ключ введен", "Ключ завершен" и т. Д.
Пытаться хранить их в одном узле - плохая идея, поскольку вы смешиваете в основном статические данные (свойства ваших элементов) с очень изменчивыми данными (информация о географическом местоположении). Разделение на два приводит к повышению производительности, поэтому Geofire обеспечивает ее соблюдение.
Хотя могут быть случаи использования, когда свойства и геоданные одинаково динамические / статические, GeoFire не поддерживает хранение геоданных и других свойств в одном месте.
Вы можете использовать функции 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);
});
}
}
Для тех, кто недавно пришел к этому посту с тем же вопросом, это возможно с библиотекой Geofirestore, которая поддерживает Geofire для приложений, созданных поверх базы данных Firebase Firestore.