Sync related data using angularfire/collection - firebase

I want to use angularfirecollection to keep one-way sync with a list of data. The structure is a list of 'things' with various properties (e.g. 'Likes') and users who each hold a subset of 'things' keys (e.g. -jsdzsdrestofkey: true). U
sing angularfirecollection (or firebase native 'on'), I can sync up all things that a particular user has... I can also grab (using firebase native 'once') each 'thing''s properties to display.
In angular, however, I need to use $apply() to inject the property data into scope for each item in the user's 'thing' list. To keep things in sync, I suppose I can use firebase's on change event... But this all requires me to create new references for each thing in a user's list.
What is the best way to approach grabbing relational data in firebase, while keeping both the list and the relational data in sync?
Thanks!
Irfaan

If I understand correctly, it sounds like you should use FirebaseIndex and feed the index directly into an angularFireCollection. Then you wouldn't need to use $apply since the thing data will already be in the $scope, and everything will stay synced:
var index = new FirebaseIndex(fb.child('users/789/thing_list'), fb.child('things'));
$scope.things = angularFireCollection(index);
// $scope.things will contain the user's things with the associated thing data

Related

Firebase restructure database automatically

I currently have an app with about 200 users and I'm trying to restructure my firebase db without breaking functionality so I can expand to other schools. I plan on pushing a required update before doing so.
Right now my database looks something like this
/users/user
/otherproperty/object
I am trying to move everything under one big "school" folder so it looks like this.
school/users/user
school/otherproperty/object
Is there a way I can change my firebase to look like this?
You could implement Firebase realtime database triggers that would fire whenever any data is added/modified/deleted under the old data hierarchy that performed the same updates in the new data hierarchy. You could also implement triggers that performed the same updates from the new hierarchy into the old hierarchy.
Then, you can migrate users from the old hierarchy into the new one at whatever rate/schedule makes the most sense to you. The triggers would maintain data consistency between the two hierarchies.
Once all users are migrated to the new hierarchy, you can remove the triggers and move forward with only the new hierarchy.
The easiest thing to do with a relatively small amount of data is write a script to get a snapshot of the data and set it in the new path.
let userRef = firebase.database().ref('users')
let newUserRef = firebase.database().ref('MYSCHOOL/users')
userRef.on('value', function(usersSnapshot) {
newUserRef.set(usersSnapshot.val())
});
You can also use the REST API and use shallow queries to grab the individual keys and query data in smaller chunks.

Fetching single records using Redux Crud?

I've been using redux-crud, and really like it. I'm still very new to Redux itself, so the following question may seem a bit noob.
I'm at the point where I want to fetch just a single record freshly from the server when I enter the edit form for it. I can't rely on the record that might have been previously fetched into the state, to be the most accurate representation of it for editing purposes.
Based on my current understanding, it doesn't seem that redux-form is suited to fetching singles, rather it seems to suggest that I pull the record for edit out of the collection of records already in the state (previously fetched with the out of the box crud actions and reducers).
I have a type of record called Providers.
Am I right to say that I'm going to have to create a separate set of fetch actions and reducers that are suited to singular fetching?
So where Redux Crud would give me PROVIDERS_FETCH_SUCCESS, I would then need to go on and implement PROVIDER_FETCH_SUCCESS in a singular fashion? Or is there a simpler way out of the box with Redux Crud that I'm not seeing clearly?
Thanks!
redux-crud will manage updating items for you when you need to fetch individual entities. actionCreatorsFor and reducersFor both take optional secondary arguments to specify what
reduxCrud.actionCreatorsFor('providers', {key: '_id'});
reduxCrud.Map.reducersFor('providers', {key: '_id'});
You can then mark the action as "replace" to replace existing items that have matching key fields;
fetchSuccess(providers, {replace: true});
Or
fetchSuccess([provider], {replace: true});

How do I create a Firebase collection?

So I am writing a chat application that I want to have multiple rooms, however, I can't find a button on the Firebase console that I can add child collections.
I've tried exporting, editing, then importing but that doesn't seem to do much. I have looked at some Firebase tutorial's but I can't find one that explains this.
Anything you enter in the console has to have a value itself, or at least one child (with a value). This is because Firebase does not explicitly store "null" or empty values in the database. You can enter the name of the collection and then rather than a value use the + button at the right to start adding children to it and so on until you reach a node with a value:
You cannot however simply create a placeholder for a collection that has no values. If you need a collection but can't initialize any of its data, just use your security rules to define what's allowed and write your client code knowing it may or may not exist. Firebase allows you to attach listeners to nodes that don't exist yet.

Firebase - Structuring Data For Efficient Indexing

I've read almost everywhere about structuring one's Firebase Database for efficient querying, but I am still a little confused between two alternatives that I have.
For example, let's say I want to get all of a user's "maxBenchPressSessions" from the past 7 days or so.
I'm stuck between picking between these two structures:
In the first array, I use the user's id as an attribute to index on whether true or false. In the second, I use userId as the attribute NAME whose value would be the user's id.
Is one faster than the other, or would they be indexed a relatively same manner? I kind of new to database design, so I want to make sure that I'm following correct practices.
PROGRESS
I have come up with a solution that will both flatten my database AND allow me to add a ListenerForSingleValueEvent using orderBy ONLY once, but only when I want to check if a user has a session saved for a specific day.
I can have each maxBenchPressSession object have a key in the format of userId_dateString. However, if I want to get all the user's sessions from the last 7 days, I don't know how to do it in one query.
Any ideas?
I recommend to watch the video. It is told about the structuring of the data very well.
References to the playlist on the firebase 3
Firebase 3.0: Data Modelling
Firebase 3.0: Node Client
As I understand the principle firebase to use it effectively. Should be as small as possible to query the data and it does not matter how many requests.
But you will approach such a request. We'll have to add another field to the database "negativeDate".
This field allows you to get the last seven entries. Here's a video -
https://www.youtube.com/watch?v=nMR_JPfL4qg&feature=youtu.be&t=4m36s
.limitToLast(7) - 7 entries
.orderByChild('negativeDate') - sort by date
Example of a request:
const ref = firebase.database().ref('maxBenchPressSession');
ref.orderByChild('negativeDate').limitToLast(7).on('value', function(snap){ })
Then add the user, and it puts all of its sessions.
const ref = firebase.database().ref('maxBenchPressSession/' + userId);
ref.orderByChild('negativeDate').limitToLast(7).on('value', function(snap){ })

How do I stop Firebase from creating an additional nested object or how can I access the newly generated string?

Problem: Whenever I add an order to the orders array, an additional nested array element(-KOPWA...) gets added. I wouldn't mind except, I don't know how to access that nested string to access it's child nodes.
Example of database node for users below:
firebase.database().ref('users/'+userIdState+'/orders/'+<<unique numbervariable>>).push({
"order":{"test":"product","quantity":2}
});
I'm using the above code to push new json objects with a unique number to the firebase array. Still the nested array with the weird strings gets generated.
Can anyone help me understand how to either: create my own nested array with my own unique string or how to access the nested string that gets generated from firebase so I can access it's children nodes.
Multiple instances of nest arrays will be generated by users.
Any help is much appreciated.
Thanks,
Moe
You're experiencing this behaviour because Firebase's push is not the same as an array push. I recommend reading this article to understand how it works.
As for a solution, you can simply change push to set in your code. This will create the structure you were (presumably) expecting, that is
1:
order:
...
This is however potentially unsafe, if you allow concurrent writes (i. e. if the "unique number" in your example is not always unique).
Afaik Firebase recommends using push to safely create collections/"arrays". You can retrieve the generated key by calling the key property on the reference returned by push. Like this:
var ref = firebase.database().ref('users/'+userIdState+'/orders/'+<<unique numbervariable>>).push({
"order":{"test":"product","quantity":2}
});
var generatedKey = ref.key; // the value you're looking for
If you decide to use it, you can probably just drop the order number you have right now and just use the generated one.

Resources