I'm having trouble trying to figure out how to get a list to query as desired. Full disclosure, it may not be possible and if that's the case then at least it will provide me with some closure. I want to query a friend's list based on presence, where friends who are active are queried on top.
Here is my database structure:
friendships
$UID
$UID: true
users
$UID
active:true/false
I need the list to stay synced so I need to use .on('value'). I've tried a couple different methods using child_added as well as iterating through a snapshot using snapshot.forEach() and pushing the childSnapshot key:value pairs into an array so I could then use lodash to order the list via the active key on the client side, but ran into the issue of it pushing a "new" item into the array for each active value change so there would be multiple items for any given user.
Any help or insight would be appreciated, spent the majority of yesterday attempting to figure this out before resorting back to an unorganized list using the following code:
const {currentUser} = firebase.auth();
firebase.database().ref(`/friendships/${currentUser.uid}`).on('value, snapshot => { //redux dispatch action, payload: snapshot.val() })
There's no great solution for this. Firebase doesn't have any sort of join or join query, so you could do usersRef.orderByChild('active').equalTo(true), but that will just return you all active users. You'll need to do separate queries to pull in their friendships.
Related
I have two array in firebase realtime database that will manage user followers and following. I've created this function in my vue app that will add the follow if an user click on the button in the profile of another user and the following into the profile of the user who clicked:
async followUser() {
await update(ref(db, 'Users/'+ this.profileKey), {
followers: [store.currentUser.uid]
})
await update(ref(db, 'Users/'+ store.currentUserKey), {
following: [this.$route.params.uid]
})
}
At the moment I've tested on two profile I've created ad-hoc and the function act as expected but I have a doubt about it. If the user will start follow other users, will the new entries will be added correctly into the existing array or all the data will be overwritten? What's the correct way to push or remove valuse into an array stored in firebase realtime database?
There is no atomic way to add an item to or remove an item from an array in the Firebase Realtime Database API. You'll have to read the entire array, add the item, and write the array back.
Better would be to store the followers and followings as maps instead of arrays, with values of true (since you can't have a key without a value in Firebase. If you'd do that, adding a new user follower would be:
set(ref(db, 'Users/'+ this.profileKey+'/followers/'+store.currentUser.uid), true)
And removing a follow would be:
set(ref(db, 'Users/'+ this.profileKey+'/followers/'+store.currentUser.uid), null)
Or
remote(ref(db, 'Users/'+ this.profileKey+'/followers/'+store.currentUser.uid))
Also see: Best Practices: Arrays in Firebase.
I have many to many relational data model. For example , i have a chat room and it has many users.
{Chatroom:
ChatRoomID:ID,
Somedata...
User:{
ID:userid,
Somedata...
}
}
I have a user object and i need to filtre those by user.
DataStore.query(ChatRoom,e=>e.User.Id("eq",myID))
I tried to query the data which has my userid then get the ChatRoomID. But i didnt work as expected. I can filter it with its main keys but i cant go through inside the object to filter. Currently i am doing this the same as the aws document. Which is-->
DataStore.query(ChatRoom).filter(e=> e.user.id==myID)
My concern is ,is this query above gets the whole data to filter ? For the first one, it looks like it getting the filtered data like select queries as we do in SQL. But i m worried about using second one. What if i have 100.000 rooms and 500.000 users inside it ? Is it get the whole data before filtering with a JavaScript functions like filter, map etc. ? I dont get the logic behind.
Im trying to make friends system but in invite accept i have to delete invite of a guy in his list but i cant do it without the key.
How do i get the snapshot key by value (in this case uid) in database?
Firebase Realtime Database queries work on single path, and then order/filter on a value at a fixed path under each direct child node. In your case, if you know whether the user is active or pending, you can find a specific value with:
const ref = firebase.database().ref("friends");
const query = ref.child("active").orderByValue().equalTo("JrvFaTDGV6TnkZq6uGMNICxwGwo2")
const results = query.get();
results.forEach((snapshot) => {
console.log(`Found value ${snapshot.val()} under key ${snapshot.key}`)
})
There is no way to perform the same query across both active and pending nodes at the same time, so you will either have to perform a separate query for each of those, or change your data model to have a single flat list of users. In that case you'll likely store the status and UID for each user as a child property, and use orderByChild("uid").
Also note that using push IDs as keys seems an antipattern here, as my guess is that each UID should only have one status. A better data model for this is:
friends: {
"JrvFaTDGV6TnkZq6uGMNICxwGwo2": {
status: "active"
}
}
I'm trying to retrieve a single document from a collection. I'm now using the code below that returns a collections of items, but I know that there is only one item. So it ain't that clean.
Setup:
private db: AngularFirestore
private itemSubs: Subscription[] = [];
itemAd= new Subject<Item>();
fetchItemFromDatabase(itemId: string) {
this.itemSubs.push(
this.db.collection('items', id => id.where('itemId', '==', itemId)).valueChanges().subscribe((items: Item[]) => {
this.itemAd.next(items);
}));
}
I tried to do it with this.db.collection('items').doc(itemId).get() , but I'm getting an error on get() that it's not found/supported. I also didn't got autocompletion when trying to call this methode (methode found in the official cloud firestore documents).
I looked at around at some other solutions and then tried it with this.db.collection('items').doc(itemId).ref.get().then(...) , but here I got an empty doc back.
So I'm a bit stuck at the moment and I don't want to use that whole collections logic when I know there is only 1 item in it.
There may be multiple documents with itemId equal to a given value. While you may know that there is only one in your app, the database and API cannot know nor enforce that. For that reason the query you run will always return a query snapshot that potentially contains multiple documents.
this.db.collection('items', id => id.where('itemId', '==', itemId))
If you want to enforce that there is only one document with the given item ID, consider using that item ID as the document name instead of storing it as a field in the document.
There can be only one document with a given name, so that means the ID is guaranteed to be unique. And you can then retrieve that document with:
this.db.collection('items').doc(itemId)
When trying to pull data from a MySQL database, I can do something like:
SELECT * FROM users ORDER BY id WHERE vehicle = car
That should get me all the users that drives a car and not show users that drives a motorcycle for instance.
Is there something like this for Firebase? I can only retrieve specific data from one user?
My firebase database is like this: user -> user info (name, age, vehicle etc..)
I want to query every user that drives a car and display them in a row. How do I do that?
I have tried the following, but I didn't succeed with what I tried to do, since after users the users id is the next child. Is there a way to query past that?
var recents = firebase.database().child('users').orderByChild('department').equalTo(department);
recents.on('child_added', function(snapshot) {
var countOfUserInDepartment = snapshot.count;
document.querySelector("#cphCount").innerHTML = countOfUserInDepartment;
});
There are no count queries (nor other aggregation queries) in the Firebase Database. Your options are:
Retrieve all data matching your query and count client-side
Keep a separate count-node that you update whenever you add/remove items.
For #2 you may find it convenient to use Cloud Functions, for which there an an example of keeping such a counter.
Also see:
Firebase count group by
Database-style Queries with Firebase
In Firebase, is there a way to get the number of children of a node without loading all the node data?
How to get size of an element/list in Firebase without get it all?