Open cmellinas opened 9 years ago
I think this is a great suggestion and I think we can find a way to work this into the API. It will be a little while before I have time to implement this, but I'm happy to code review PRs from the community. Otherwise, once I have some time to take a crack at this, I'll go ahead and see how we can support this kind of feature. Thanks for opening this issue!
Ah great Jacob Hope you will found a solution
Many thanks, Clément
+1. Atomic updates are really important to ensure the integrity of the database.
Do we have a solution for the problem now.
+1
maybe instead return _firebaseRef.update(newData);
use return newData
; ... then we can use ref().update function with other data
Playing fast and loose here, so disregard if this is totally whacked, but couldn't we just have a method that returns the geofire data that would be updated? Then we could just use the existing atomic update api.
Any movement on this? I like @jcheroske's suggestion as long as there isn't any behind the scenes wizardry in the "set" method that would confound this solution
checking the set function inside module at ../node_modules/geofire/dist/geofire/index.cjs.js" there wasn't really sophisticated method or external library that help update geofire hash to firebase. It's just plan method and validation.
as @ghost suggested earlier, instead of returning a promise for updating the data, you can simple return newData, then do the uploading yourself.
you can simply copy and paste below function, then you can do something like
`var map = {}; map['eventIndex/' + v] = getGeoFireHashes(eventKey, [location.lat, location.lon]);
firebase.database().ref('/').update(map);`
`function getGeoFireHashes(keyOrLocations, location) { var locations; if (typeof keyOrLocations === 'string' && keyOrLocations.length !== 0) { // If this is a set for a single location, convert it into a object locations = {}; locations[keyOrLocations] = location; } else if (typeof keyOrLocations === 'object') { if (typeof location !== 'undefined') { throw new Error('The location argument should not be used if you pass an object to set().'); } locations = keyOrLocations; } else { throw new Error('keyOrLocations must be a string or a mapping of key - location pairs.'); } var newData = {}; Object.keys(locations).forEach(function (key) { validateKey(key); var location = locations[key]; if (location === null) { // Setting location to null is valid since it will remove the key newData[key] = null; } else { validateLocation(location); var geohash = geohashForLocation(location); newData[key] = encodeGeoFireObject(location, geohash); } }); return newData; }
/**
/**
/**
function validateKey(key) {
var error;
if (typeof key !== 'string') {
error = 'key must be a string';
}
else if (key.length === 0) {
error = 'key cannot be the empty string';
} else if (1 + GEOHASH_PRECISION + key.length > 755) {
// Firebase can only stored child paths up to 768 characters
// The child path for this key is at the least: 'i/
function validateLocation(location) { var error; if (!Array.isArray(location)) { error = 'location must be an array'; } else if (location.length !== 2) { error = 'expected array of length 2, got length ' + location.length; } else { var latitude = location[0]; var longitude = location[1]; if (typeof latitude !== 'number' || isNaN(latitude)) { error = 'latitude must be a number'; } else if (latitude < -90 || latitude > 90) { error = 'latitude must be within the range [-90, 90]'; } else if (typeof longitude !== 'number' || isNaN(longitude)) { error = 'longitude must be a number'; } else if (longitude < -180 || longitude > 180) { error = 'longitude must be within the range [-180, 180]'; } } if (typeof error !== 'undefined') { throw new Error('Invalid GeoFire location \'' + location + '\': ' + error); } }`
Hi,
As mentioned here, I think it should be great to easily multi update data paths and a geofire path at the same time. As the set of Geofire is pretty complex, it's hard to directly copy/paste the code to make it works.
Here the use case : (I use the same as the link above but add a path to know where a post is located). So the structure :
Now I can add a post at the same time at users and posts (with multi-path update). But I need to set the position after. In my use case, a post without a position is not valid data, it's for that the best should be to do the 3 updates at the same times (if one fails, all fail).
Deleting Geofire path is easy (using update(null)), we can multi-update for delete, but for set/update, I loop for a way to do that easily,
Cheers, Clément