Document reference in firestore using react-native(javascript) - javascript

Document Reference is used to get document field and its collections from firestore. Following are some examples:
1. Function to read data from field which is having docRef
[Firestore schema]: https://i.stack.imgur.com/pEPK5.png
Here in collection people there is doc named user1 which have a field named hlpr which have docRef for user2 so if i want to access that docRef data i will use following code:
function foo4() {
var user1 = db.collection('people').doc('user1')
user1.get().then((data) => { //get user1 whole doc using get()
var t = data.get('hlpr') //choose field 'hlpr'
t.get().then((doc) => { //get 'hlpr' data() from get()
var user2 = doc.data() //get whole doc from user2
console.log(user2.name) //output field 'name' from user 2
})
})}
2. Read data from array from of docRef. In previous image you can see field named 'cts' which is having array of docRef. Code:
function foo3() { //function to get data from array of docRef
var user1 = db.collection('people').doc('user1'); //choose user1 doc
user1.get().then((doc) => { //get data() of user1 using get()
var contacts = doc.get('cts'); //set var k to field 'cts'
contacts.forEach((data) => { //for each item in array field cts
var userx = data.get(); //read data() using get()
userx.then((doc) => {
var frnd = doc.data(); //set frnd to each data we get from doc
console.log(frnd.name) //output their any field value here i have chosen name
});
});
})}
NOTE: Above code works correctly and you can also use data to put into array also above code might not be best way to get data, but i am a beginner so this is the best i could do.

You can break your code down to a chain of awaits per the comments but a promise chain if processing one item can be fairly clean.
async function foo4() {
var user2 = await db.collection('people').doc('user1').get()
.then(data => data.get('hlpr'))
.then(doc=> doc.data())
.finally(result => result)
.catch(console.log());
you can do some clean code when you nest promise chains.
The second code block has potential errors, if your client exceeds pending 50 documents the client modules will throw errors and fail reads.

Related

how to update a map FIRESTORE value with a key JAVASCRIPT

collection name user and a collection name query.
each user document holds a map name seenQueries with string (queryID) : number.
given a user and a queryID (key) i wish to update its number (the value). the rest of the documents fields should remain untouched.
function updateQuerySeen(userID, queryId) {
var userRef = db.collection("users").doc(userID);
var queryRef = db.collection("query").doc(queryID);
const promise1 = userRef.get();
const promise2 = queryRef.get();
Promise.all([promise1, promise2]).then((values) => {
doc1 = values[0];
doc2 = values[1];
curMsgArrayLen = doc2.data().msgArrayLen;
// Uupdate seenQueries map key:queryID
userRef.update({
seenQueries.queryID: curMsgArrayLen; // DOESN'T SEEM TO WORK
}).then(function () {
//console.log("setDocument);
})
.catch(function (error) {
console.error("UPDATE user's seen query failed ", error);
});
});
looked at google API, but it doesn't seem to work https://firebase.google.com/docs/reference/rules/rules.Map
saw this answer Update individual map in cloud firestore document but wasn't sure which one fits my objective, and this one How to update fields in Firestore map didn't work
thank you!

Unable to retrieve data from Cloud Firestore using queries

I am attempting to retrieve a collection of data from my Cloud Firestore, so that I can arrange the data in a "Bootstrap" Table, displaying the name and the score from the Firestore documents.FireStore Layout Here.
I have created a reference to the user collection and queried this to obtain data, however when I run this it throws an exception "Uncaught ReferenceError: querySnapshot is not defined".
<script>
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.orderBy("score", "desc").limit(10); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //If query is needed
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
querySnapshot.docs.map(function (documentSnapshot) {
var name = documentSnapshot.data().name;
var score = documentSnapshot.data().score;
console.log(name + score);
});
}
});
</script>
My aim is to retrieve all of the documents inside the user collection, order and sort them using the inbuilt .limit and orderBy methods, then store them in an array so that they can be displayed using a "Bootstrap" table.
var query = usersCollectionRef.orderBy("score").limit(10); //Selects the 10 highest scoring player's documents
Note for potential readers: the fist part of the answer corresponds to the initial question of the OP, before it was edited.
You have to put the second part of your code within the then() function, as below.
This is because get() returns "a promise that will be resolved with the results of the query." (see the Ref https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#get)
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.where("name", "==", "Steeve"); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //Call get() to get a QuerySnapshot
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
querySnapshot.docs.map(function (documentSnapshot) {
//Not necessary to do that -> return documentSnapshot.data();
console.log(documentSnapshot.data().name);
});
}
});
EDIT following your comment:
In case you would have several documents for a given name which hold a different score (in a number field score), you could get the total score like that:
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.where("name", "==", "Steeve"); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //Call get() to get a QuerySnapshot
var score = 0;
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
var data = querySnapshot.docs.map(function (documentSnapshot) {
//Not necessary to do that -> return documentSnapshot.data();
console.log(documentSnapshot.data().name);
score += documentSnapshot.data().score;
});
}
console.log(score);
});
EDIT after edit of the original post
Do like that
var query = usersCollectionRef.orderBy("score", "desc").limit(10); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //If query is needed
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
var nameArray = Array.from(querySnapshot.docs, x => x.data().name);
console.log(nameArray);
var scoreArray = Array.from(querySnapshot.docs, x => x.data().score);
console.log(scoreArray);
}
});
Explanations:
querySnapshot.docs returns "An array of all the documents in the QuerySnapshot." (See Ref: https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot#docs)
Then you use Array.from() to create the two arrays (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)

Creating a field in a Firestore collection from a field referenced in another Firestore collection using Google Cloud Functions

I am trying to create a field ("artistName") in a Firestore collection ("shows") that is pulling from a field ("name") in another Firestore collection ("artists"). The "shows" collection has a reference field ("artist") that points to the a document in the "artists" collection. To create the field, Im using Google Cloud Functions. Here is my code:
exports.addReferenceDataToCollection = functions.firestore
.document('shows/{showId}').onWrite(event => {
var newValue = event.data.data();
var artistId = newValue.artist.id;
var artistRef = firestore.collection('artists').doc(artistId);
return event.data.ref.set({
artistName: artistRef.get().then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc.data());
var artistName = doc.data().name;
console.log('Artist Name:', artistName);
return Promise.resolve(artistName);
}
})
}, {merge: true});
});
I cant seem to get the data out of the promise.
You need to do artistRef.get() first, then after you have the document you need, use its data in event.data.ref.set(). As you've written it now, you're assigning a promise object to the artistName property.
The general form of this type of pattern looks like this:
// First get the artist doc
return artistRef.get().then(doc => {
return event.data.ref.set({
// use the properties of the doc in here
})
})

Checking data in deep array with includes (Firebase retrieve data JS)

So I am new to the Firebase database and what I like about it is that I don't have to build a whole backend for just storing some simple data. What I am trying to do is pushing data to an array that I like to recieve from firebase. Then after that I would like to check if the email that was filled in, is included in the data from the firebase database. But because it's firebase and it has multiple arrays, objects etc I don't know how to check that. So the flow is: User fills in data, Applications makes a call to the firebase db and the Application is retrieving the current data from firebase. Then the Application will check if the data that is inputed is already there, and if so, will throw an alert that the data is already in the database. If not, the data will be submitted.
Also, I am wondering if this is the right way to retrieve data from the database:
Main.js
function writeUserData() {
var name = document.getElementById("name").value;
var email = document.getElementById("email").value;
firebase.database().ref('/aanmeldingen/').push({
username: name,
email: email,
});
var dbRef = firebase.database().ref().child('/aanmeldingen/');
dbRef.on('value', snapshot => {
const snap = snapshot.val();
const array = [];
array.push(snap);
console.log(array);
const res = array.includes(email);
console.log(res);
console.log(email);
});
}
Output in console
As you can see this returns multiple data. The include function will check on the submitted emailadress. This returns false even I had inputted "info#webpack.com". How can I check the right data object? It has to check all objects under "0" and return in the console if the submitted emailadress is already there.
I haven't tested it yet but i hope you get the idea. Also this is not the most efficient way to do this.
function ifEmailExist(arr,email){
var _t = 0;
for(var x in arr){
for(var y in arr[x]){
if(arr[x][y].email){
if(arr[x][y] === email){
_t++;
}
}
}
}
return _t;
}
Usage:
if(ifEmailExist(arr,"info#webpack.com") > 0){
//do stuff
}
You should use child_added instead of value. Whenever a new node is added in database, child_added will trigger and then you can take action on the data.
var dbRef = firebase.database().ref().child('aanmeldingen');
dbRef.on('child_added', snapshot => {
var username = snapshot.val().username;
var email = snapshot.val().email;
console.log(username);
console.log(email);
});

Get json array from sub mongoose query

I have a sub query in mongoose need to get array out of sub query and attach to main json out put/ object.
my first query get user info which contains blocked_users array which is nothing but array of user id's.
i my second query we get profile details of blocker_users array and append to main user object in blocked_users.
var userId = ObjectID(req.body.user_id);
//Get user
newUserModel.findById(userId, function(err, user){
if(err){
utils.getResponse(res, req.url, messages.failure, "");
} else {
var userInfo = {};
var blcked_contacts;
//get users details from blocked contacts userid's array
newUserModel.find({'_id': {$in:user.blocked_contacts}}, function (err,blocked_users) {
if(blocked_users){
//blcked_contacts.push(blocked_users);
console.log(blocked_users);
return;
};
/*else{
blcked_contacts = [];
}*/
});
userInfo['blocked_contacts'].push(blocked_users);
userInfo['user_id'] = user.id;
userInfo['country_code'] = user.country_code;
//userInfo['blocked_contacts'].push(blcked_contacts);
//userInfo['blocked_contacts'] = user.blocked_contacts;
var userData = Array();
}
});
Don't really know what you're looking for. But saw a problem in your code. You've assigned the blocked_users to the blocked_contacts field outside the find method.
Since these calls are asynchronous in nature, it might happen that the assignment takes place even before the documents are fetched from MongoDB. So you should write your assignment statements inside the find methods' callback, just the way Medet did.
Noticed few mistakes in your code like trying to use .push on an object. You cant do
userInfo['blocked_contacts'].push(blocked_users); // incorrect as userInfo is an empty object and you dont have an array defined for userInfo['blocked_contacts']
You probably get cannot push into undefined error for this. So instead do
userInfo['blocked_contacts'] = blocked_users;
Also you have to do this inside the second find() as blocked_users is only available inside it. So your final query should be something like
var userId = ObjectID(req.body.user_id);
//Get user
newUserModel.findById(userId, function(err, user){
if(err){
utils.getResponse(res, req.url, messages.failure, "");
} else {
var userInfo = {};
//get users details from blocked contacts userid's array
newUserModel.find({'_id': {$in:user.blocked_contacts}}, function (err,blocked_users) {
if(blocked_users){
userInfo['user_id'] = user.id;
userInfo['country_code'] = user.country_code;
userInfo['blocked_contacts'] = blocked_users; // assign blocked_users into userInfo
console.log(userInfo) // Your required object
} else {
userInfo['user_id'] = user.id;
userInfo['country_code'] = user.country_code;
userInfo['blocked_contacts'] = []; // assign null array if no blocked users fould
}
});
var userData = Array();
}
});
The result of console.log should be an object like this
{
user_id : "..id of searched user...",
country_code : "..country code of searched user..",
blocked_contacts : [<array containing detais of all blocked users>] // null array if no users found
}

Categories