How to get value from firebase without the snapshot key [JS] - javascript

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"
}
}

Related

firebase - add and remove new values into an array

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.

Saving a field from firestore that is an array

I am currently working on a mobile app on React and I am having trouble understanding how to save a field from fire store that is an array.
Since I can't post images my database structure is all strings such as username, first name, etc but I have a field called follow list that is an array.
What I want to do is save the usernames from the following list into an array to later search fire store for the username's in the array, this is basically what I want to do so I can render my app's social Feed. I do know that I can probably create another subcollection and write something familiar to what I did to search for users but that was a QuerySnapShot which was overall documents not a specific one and I also know firebase creates an ID for arrays and it increases as the array gets bigger.
I do not want to end up making two more subcollections one for followers and following which I think not ideal right? My current approach is this
export const fetchUserFollowing = async (username) => {
const ref = firebase.firestore().collection('users').doc(username)
let results = []
ref
.get()
.then( doc => {
let data = doc.data()
results = data
})
.catch((err) => {
return 'an error has occurred ', err
})
}
From what I understand is that a DocumentSnapShot .get() function returns an object but what I want is to store follow list into results and then return that but I am not sure how to manipulate the object return to just give me follow List which is an array
https://rnfirebase.io/docs/v5.x.x/firestore/reference/DocumentSnapshot
link to docs

Cloud FireStore: Retrieve 1 document with query

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)

Firebase order query $UIDs by value at a different node

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.

fiirebase result.val is null with await

What is the response structure of firebase queries? Is there any documentation? I couldn't find anything. I don't why user is null below. Do I need to run for loop and get the first item?
const result = await firebase.child('users').orderByChild('email')
.equalTo(memberEmail).limitToFirst(1)
.once('value');
const user = result.val();
the following code works, but I don't want to run a loop to get single value. How do I get the user without running a loop?
result.forEach((value) => {
alert(`user = ${JSON.stringify(value.val())}`);
});
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result. So if you use a query, you will always need a loop.
The way to not require a loop is by directly accessing the child node that you are looking for. In your current data structure you likely store the users by their uid, so you can only access them directly by uid:
const result = await firebase.child('users').child(currentUser.uid).once('value');
const user = result.val();
If you'd store the users by their email address (you'll have to encode it, since a . cannot be used in the key), you could also access the users by their email address.
An idiomatic way to do this with Firebase is to keep a separate node that maps email addresses to uids. You'd then do two direct lookups:
firebase.child('emailToUid').child(email)
firebase.child('users').child(uid)
Each of those would return a single node (or no node if there is no match found), so you could chain the awaits and won't need a loop

Categories

Resources