I'm trying to do a comparison between user session email and an email in an array in firestore. That is, I want to search for the login email within the database and if any email is found, bring some information to the screen, such as name and surname.
I even managed to get inside the array and make this comparison, but I can't make the "var UserName" leave the { } of the IF
Can someone help me?
my code is:
const [data, setData] = useState([]);
const getUsers = () => {
firestore()
.collection("users")
.get()
.then((querySnapshot) => {
let userFirestore = [];
querySnapshot.forEach((doc) => {
const usuario = {
id: doc.id,
nome: doc.data().nome,
sobrenome: doc.data().sobrenome,
email: doc.data().email,
profissao: doc.data().profissao,
}
userFirestore.push(usuario);
});
userFirestore.forEach(function (item, indice, array) {
if (item.email === user.email){ //user.email brings the email of the logged in user
var nomeUsuario = item.nome
console.log(nomeUsuario) //UserName brings the result I expected
}
});
})
.catch((error) => console.log(error));
}
You can use a query to get a document with current user's email that instead of fetching the whole collection as shown below:
firestore()
.collection("users")
.where("email", "==", user.email)
.get().then((querySnapshot) => {
if (querySnapshot.empty) {
console.log("User not found")
return;
}
const user = querySnapshot.docs[0].data();
console.log(user)
})
Even better, if you use user's UID as the Firestore document ID (highly recommended), then you can get that single document by ID as shown below:
firestore()
.collection("users")
.doc(user.uid) // < user.uid must be defined
.get()
.then((snapshot) => {
console.log(snapshot.data())
})
When you fetch the whole collection, you are charged N read where N is total number of documents in the collection and it'll be slower as you are downloading plenty of data.
Related
heys guys I want to get logged in user data from Firestore using react and firebase v9 but in the console I am getting data of all the users
here my code:
const usersCollectionRef = collection(db, "users");
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
getDocs(usersCollectionRef, user.uid).then((snapshot) => {
console.log(snapshot);
});
}
});
}, []);
I want to get the data of only logged in user.
Instead of of fetching all the documents in the users collections, you can fetch a single document as long as you know the document ID. You can use doc() to create a DocumentReference to that user's document and then use getDoc() to get that:
useEffect(() => {
onAuthStateChanged(auth, async (user) => {
if (user) {
const snapshot = await getDoc(doc(db, "users", user.uid))
console.log(snapshot.data())
}
});
}, []);
I'm trying to get a doc in a collection and if it doesn't exist I create a new one, I would like to know if there is any way to get userData even if it doesn't exist (so to assign it the new one I have created) or I need to take it with
firebase
.firestore()
.collection("users")
.doc(ID);
again
const userRef = firebase
.firestore()
.collection("users")
.doc(ID);
const user = await userRef.get();
if (!user.exists) {
userRef.set(userSchema);
}
const userData = user.data();
I'm not sure where the user data is coming from but let's have a test user as follows:
const userData = {
name: "TestUser",
uid: "1234",
verified: true
}
Then here goes the function you need:
async function addUserToDatabase(userData) {
//Document Reference
const userDocRef = admin.firestore().collection("users").doc(userData.uid)
//Checking if document exists
if ((await userDocRef.get()).exists) {
return "User document already exists!"
}
//Document does not exists so create one
await userDocRef.set(userData)
return
}
I am trying to conduct simple search query as below.
SELECT post.title as "Post Title", user.email as "Author Email"
FROM User
JOIN Post ON User.id = Post.userID
WHERE Post.title LIKE '%retriever%';
I know I can't do join search on nested collection
so I ended up creating two root collections: users, posts.
Below is my pathetic try on such query
const db = firebase.firestore()
const ref = db.collection('Post')
const postTitle = await ref
.orderBy('title')
.startAt('Springfield')
.get();
const userEmail = await db.collection('User')
.where('id', '==', 'postTitle.userId')
.document('email');
How do I achieve the above result in this particular case?
Alright, first let me confirm I understand the SQL.
You're wanting to return two variables (title, email) from the User table
SELECT post.title as "Post Title", user.email as "Author Email"
FROM User
Then you want to join the Post table where the 'User.id' is equal to the 'Post.userID' so essentially finding the users' posts.
JOIN Post ON User.id = Post.userID
WHERE Post.title LIKE '%retriever%';
If my assessment is accurate, and without knowing your data model, I can give a rough guess on what that would look like.
//Reference to Firestore
const db = firebase.firestore()
//Reference to the Post "table" Collection
const ref = db.collection('Post')
//This is assuming I know the USER ID that I need - if I don't have it, we can retrieve it by their email 'admin.auth().getUserByEmail(email)' or somewhere else.
//This example should still work with whatever the 'id' key is representing in the Post model
const postsByUserID = await ref.where('id', '==', userID).get();
if (postsByUserID.empty) {
console.log('No matching documents.');
return;
}
//This will loop through every Post that we got that matched the user's ID
postsByUserID.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
Keep in mind this is assuming that 'id' from your Post model is equal to a user's UID.
If we assume we do not know the user's ID, and want to get every user, and then the posts that have the 'id' equal to that user's id:
//Reference to the Post "table" Collection
const ref = db.collection('Users')
const allUsers = await ref.get();
allUsers.forEach(doc => {
console.log(doc.id, '=>', doc.data());
const userID = doc.data().id;
const postsByUserID = await ref.where('id', '==', userID).get();
if (postsByUserID.empty) {
console.log('No matching documents.');
return;
}
//This will loop through every Post that we got that matched the user's ID
postsByUserID.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
});
constructor(props) {
super(props);
this.state = {
users:[]
};
}
//method to get the data from users collection
async componentDidMount() {
const db = firebase.firestore();
db.collection("users")
.get()
.then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.data());
console.log(data);
this.setState({ users: data });
})
.catch( err =>{
console.log(err);
});
}
this function returning an empty error
i want to print list of users uid
here i have users collection and inside it i have retailers collection and its document
One thing you have to realize here is that your users collection contains no documents. The document IDs are shown in italics, which means that there is no document here. The IDs are visible because there is a nested subcollection under each document. They are shown like this in the console so that you can click through and navigate to the nested subcollection, despite the document being missing.
If you want to list users with a query, you will have to actually create documents in the users collection. They can be empty if you don't have any information. But you do need actual documents in the users collection in order for anything to show up in a query.
This line in your current code querySnapshot.docs.map(doc => doc.data()) takes the data of each document. But you're keeping the UID in the ID of each document, so you'll want to use:
const db = firebase.firestore();
db.collection("users")
.get()
.then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.id);
console.log(data);
this.setState({ users: data });
})
.catch( err =>{
console.log(err);
});
Update: As Doug pointed out in his answer, if there are no actual user documents, your get() call will not return it.
I highly recommend creating user documents, even if it's just an empty one.
For now, the only way to get the UID would be to load all retailers for all users, and then use those results to get the ID of the parent documents:
const db = firebase.firestore();
db.collectiongroup("retailers")
.get()
.then(querySnapshot => {
querySnapshot.forEach((doc) => {
console.log("retailed "+doc.id+" for user "+doc.ref.parent.parent.id);
});
})
.catch( err =>{
console.log(err);
});
You'll have to deduplicate the UIDs, but that will leads to getting the UIDs.
But you'll be loading all retailers for all users this way, so as said, I highly recommend storing a small/empty user document instead.
The data method on querySnapshot.docs gets the data now to get the id of each document you need to add access the id property as UID is stored in id property
async componentDidMount() {
const db = firebase.firestore();
db.collection("users")
.get()
.then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.data().id);
console.log(data);
this.setState({ users: data });
})
.catch( err =>{
console.log(err);
});
}
I try to put a listener on Firebase that will replicate a value in the matching element in Firestore.
exports.synchronizeDelegates = functions.database.ref(`delegates/{userId}/activities`).onUpdate((event) => {
const userKey = event.data.ref.parent.key
console.log("User Key:" + userKey)
return admin.database().ref(`delegates/${userKey}/email`).once('value', snapshot => {
let email = snapshot.val()
console.log("Exported Email:" + email)
const userRef = admin.firestore().collection('users')
const firestoreRef = userRef.where('email', "==", email)
firestoreRef.onSnapshot().update({ activities: event.data.toJSON() })
}).then(email => {
console.log("Firebase Data successfully updated")
}).catch(err => console.log(err))
}
)
This function is able to retrieve and locate the elemnt needed to target the right document in firestore, but the .update()function still error firestoreRef.update is not a function
I try several ways to query but I still have this error.
How to properly query then update a document in this scenario?
The onSnapshot() method of Query introduces a persistent listener that gets triggered every time there's a new QuerySnapshot available. It keeps doing this until the listener is unsubscribed. This behavior is definitely not what you want. Also, there's no update() method on QuerySnapshot that your code is trying to call.
Instead, it looks like you want to use get() to fetch a list of documents that match your query, then update them all:
exports.synchronizeDelegates = functions.database.ref(`delegates/{userId}/activities`).onUpdate((event) => {
const userId = event.params.userId
console.log("User Key:" + userKey)
return admin.database().ref(`delegates/${userId}/email`).once('value', snapshot => {
let email = snapshot.val()
console.log("Exported Email:" + email)
const usersRef = admin.firestore().collection('users')
const query = usersRef.where('email', "==", email)
const promises = []
query.get().then(snapshots => {
snapshots.forEach(snapshot => {
promises.push(snapshot.ref.update(event.data.val()))
})
return Promise.all(promises)
})
}).then(email => {
console.log("Firebase Data successfully updated")
}).catch(err => console.log(err))
}
Note that I rewrote some other things in your function that were not optimal.
In general, it's a good idea to stay familiar with the Cloud Firestore API docs to know what you can do.