I have in firebase firestore a Collection named users created with docs of unique id.
Now I would like to push them in an Array.
(In the usersCollection there are 3 users stored with the currentUser.uid)
Example:
fb.usersCollection.where("state", "==", 'online').get().then(querySnapshot => {
querySnapshot.forEach((doc) => {
const userName = doc.data().name
this.markerMy = { name: userName }
})
// push userName inside randomArray
const randomArray = []
randomArray.push(this.markerMy)
I only get it so that I can push one user inside the Array, but not more.
You should declare randomArray before fb.usersCollection and call the push operation inside the callback as follows :
const randomArray = []
fb.usersCollection.where("state", "==", 'online').get().then(querySnapshot => {
querySnapshot.forEach((doc) => {
const userName = doc.data().name
this.markerMy = {
name: userName
}
randomArray.push(this.markerMy)
})
});
Related
I have action in vuex. This action do request to firebase.
I would like to receive record from firebase by 'id'.
But I don't know where I must input this 'id' for searching in database.
I did it here:
const snapshot = await get(child(dbRef, `/users/${uid}/records`), id);
but I receive all records, without filtration by 'id'.
async fetchRecordById({ dispatch, commit }, id) {
try {
let record
const uid = await dispatch('getUid')
const dbRef = ref(getDatabase());
const snapshot = await get(child(dbRef, `/users/${uid}/records`), id);
record = snapshot.val()
if (record === null) {
record = {}
}
return {...record, id}
} catch (e) {
commit('setError', e)
throw e
}
},
For version 8 firebase it looks like:
const record = (await firebase.database().ref(`/users/${uid}/records`).child(id).once('value')).val() || {}
How to integrate in version 9?
The get() function only takes one DatabaseReference as a parameter but you are also passing the id.
Instead, you can specify the path directly in ref() function as shown below:
console.log(uid, id) // <-- check if values are correct
const dbRef = ref(getDatabase(), `/users/${uid}/records/${id}`)
const snapshot = await get(dbRef);
console.log(snapshot.val())
var emp = db.collection('BookedTicketData').get().then((snapshot) => {
snapshot.docs.forEach((doc) => {
data = doc.data();
bseat = data.AllSeat
// console.log(bseat)
allseat.concat(bseat)
})
console.log(allseat)
return allseat;
}).then((alls) => {
console.log(alls)
})
I have done this code to get the array from the doucumnets of firebase and it is coming seperatly i want to combine all the array in single array and print the array in console.log(alls)
1-> [4,46,324,346,345,234,3446,36]
2-> [324,6,3,44,6,2,6,35,2,7,23]
alls -> [4,46,324,346,345,234,3446,36,3244,6,3,44,6,2,6,35,2,7,23]
If I correctly understand your question, the following should do the trick:
var emp = db
.collection('BookedTicketData')
.get()
.then((snapshot) => {
let allseat = [];
snapshot.docs.forEach((doc) => {
data = doc.data();
bseat = data.AllSeat;
// console.log(bseat)
allseat = allseat.concat(bseat);
});
console.log(allseat);
return allseat;
})
Hello, I have made Firebase function which is watching if users matched.
All parts work, but i added one more method getUserDataById where i want to get extra data from users, it returns undefined.
So this is what i tried:
exports.UserPressesLike = functions.database
.ref('/users/{userId}/matches/{otherUserId}')
.onCreate(async (snapshot, context) => {
// Grab the current value of what was written to the Realtime Database.
const original = snapshot.val();
const userId = context.params.userId;
const matchedUserId = context.params.otherUserId;
const a = await checkUserMatch(userId, matchedUserId);
if (a === true) {
console.log('Its a match');
addNewChat(userId, matchedUserId);
//create chat for both users
} else {
console.log('There is no match');
//do nothing
console.log(a);
}
return null;
});
checkUserMatch = async (userId, matchedUserId) => {
const isLiked = await admin
.database()
.ref('/users/' + matchedUserId + '/matches/' + userId)
.once('value')
.then(snapshot => {
// let tempuserId = snapshot.val();
// if()
let isLiked = snapshot.exists();
console.log(isLiked);
return isLiked;
})
.catch(error => {
console.log(error);
return snapshot;
});
return isLiked;
};
addNewChat = async (userId, matchedUserId) => {
const user1 = await getUserDataById(userId);
const user2 = await getUserDataById(matchedUserId);
console.log(JSON.stringify('User data: ' + user1));
const snapshot = await admin
.database()
.ref('/chats')
.push({
members: { [userId]: true, [matchedUserId]: true },
[userId]: { username: [user1.username] },
[matchedUserId]: { username: [user2.username] },
});
};
getUserDataById = async userId => {
const snapshot = await admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => {
let data = childsnapshot.val();
return data;
});
};
But I get error:
TypeError: Cannot read property 'username' of undefined
at addNewChat (/srv/index.js:93:36)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
The problem is in getUserDataById method. Because it returns undefined.
Where I made mistake?
Why I get username: { 0 : emilis} it should be username: emilis??
Part 1: getUserDataById returns undefined
You forgot return snapshot in your async function. (However, as it as a plain object, not a snapshot, I would rename the variable)
getUserDataById = async userId => {
const userData = await admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => {
let data = childsnapshot.val();
return data;
});
return userData;
};
However, I would flatten it to the following (which is identical to the above, yet concise):
getUserDataById = userId => {
return admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => childsnapshot.val());
};
Part 2: Why is my data returned as {username: {0: "Emilis"}}?
{0: "Emilis"} being returned as an object, not an array, is caused by how Firebase stores arrays in the Realtime Database. There is quite a comprehensive article on arrays on the Firebase Blog covering these quirks which I recommend reading. I'll summarise the key ones here.
When any array is stored in the Realtime Database it is stored in it's object form where {username: [user1.username] } will be stored as {username: {0: "someusername"} }. Because JSON is typeless, the Realtime Database no longer understands this entry to be an array. An array with multiple entries will also be stored stored as a plain object ([value1, value2] will become {0: value1, 1: value2}).
When the Firebase JavaScript SDK downloads data from the Realtime Database, it checks the keys of any objects for a mostly sequential numeric sequence (0,1,2,3,... or 0,1,3,4,...) and if detected, converts it to an array using null for any missing entries.
As {0: value1, 1: value2} contains the sequential keys 0 and 1, it will be parsed as [value1, value2].
As {0: "someusername"} does not contain a sequence of keys, it is returned as-is.
To bypass this, remove the single entry array and use it's value directly (as below) or explicitly convert it to an array in your client code.
addNewChat = async (userId, matchedUserId) => {
const user1 = await getUserDataById(userId);
const user2 = await getUserDataById(matchedUserId);
console.log(JSON.stringify('User data: ' + user1));
return admin // don't forget to return the Promise!
.database()
.ref('/chats')
.push({
members: { [userId]: true, [matchedUserId]: true }, // FYI: these are "use value as the key" instructions not arrays.
[userId]: { username: user1.username },
[matchedUserId]: { username: user2.username },
});
};
ive had a lot of trouble with firebase arrays, im now using push
I have this
I want to pull all the users down so I do this:
export const pullFromFirebase = () => {
return firebase
.database()
.ref("/users/")
.once("value")
.then(snapshot => {
var users = [];
snapshot.forEach(user => {
users.push(user.val());
});
return users;
});
};
this is fine
however, I now need the unique id -LI7d_i_BmrXktzMoe4p that firebase generated for me so that I can access this record (i.e. for updating and deleting) how do i do this?
You can get the key of the snapshot with the key property: https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#key
So you could change your code to this:
export const pullFromFirebase = () => {
return firebase
.database()
.ref("/users/")
.once("value")
.then(snapshot => {
var users = [];
snapshot.forEach(user => {
let userObj = user.val();
userObj.id= user.key;
users.push(userObj);
});
return users;
});
};
You can change this part:
snapshot.forEach(user => {
users.push(user.val());
});
To instead be:
let usersObj = snapshot.val()
for (var user_id in usersObj) {
users.push(Object.assign(usersObj[user_id], {
user_id: user_id,
});
});
That way, instead of each element in the users array only having email, name and username fields, it has user_id as well.
I am trying to get contact numbers from the phone using expo react native. after accessing the contacts object. The phone numbers are in the phoneNumber array. The array has a series of objects and each object has the digits in the digits key. My action creator is below that will store the data in database for now. I will change it to local storage later.
https://docs.expo.io/versions/latest/sdk/contacts.html#content
export const setContacts = (contacts) => async dispatch => {
// set the contacts object into firebase and load it into redux
// contacts is an array of objects; convert it object with key phone number
// key should be phoneNumbers; phoneNumbers is an array of phone numbers
// function below converts array to object to save to database with key for each object
// whenever getting information outside app validate and format for storage into db
console.log(contacts, 'this is the contacts object inside setContacts action');
// filter contacts that don't have phoneNumber
const arrayToObject = (array, keyField) =>
array.filter(item => item[keyField].length !== 0)
.map(item2 => {
const item3 = item2;
item3.keyField = item2.keyField
.filter(item => item.digits.length === 10 || item.digits.length === 11)
.map(item4 => {
const item5 = item4;
item5.digits = item4.digits.length === 11 ?
item4.digits.substr(1) : item4.digits;
return item5;
});
return item3;
})
.reduce((object, item) => {
const accumulator = object;
accumulator[`${item[keyField][0].digits}`] = item.name;
return accumulator;
}, {});
// object of objects to save in db
const phoneNumbers = 'phoneNumbers';
const contactsObject = arrayToObject(contacts, phoneNumbers);
console.log(contactsObject, 'this is the contactsObject inside setContacts action');
// save into firebase
const user = await firebase.auth().currentUser;
if (user !== null) {
await firebase.database().ref(`/users/${user.uid}/contacts`)
.set(contactsObject)
.then(() => console.log('contactsObject set into /users/uid/contacts inside setContacts action'))
.catch((e) => console.error(e));
console.log(contactsObject, 'contactsObject inside setContacts action before dispatch');
dispatch({ type: CONTACTS, payload: contactsObject });
} else {
console.log('user object was not found inside setContacts action');
}
};
the above code doesn't work. I think there is error in my logic specifically the arraytoObject function. i just need help with fixing the cod