I'm building an edit profile flow and I hit a huge roadblock. I have User Data stored in a firestore database and I am trying to query the contents of a collection but the if/else statement isn't running.
Here is my current code:
const userQ = query(
collection(db, "users"),
where("username", "==", username)
);
const queryName = await getDocs(userQ);
queryName.forEach((doc) => {
if (doc.exists()) {
console.log("ERROR. Username taken.");
} else {
console.log("User is available");
}
});
Problem
When a document with the user exists in the collection, it logs the appropriate object to the console. So I know my data structure and routing are correct.
However, when it doesn't exist, nothing gets logged at all, so it totally skips the else statement. I've tried using .length and .size, and nothing has worked.
This question below is basically the same as what I'm asking, but it's for firebase v8 and applying the same ideas did not work for me.
else statement not running after firebase query
Thank you!
If there are no results, calling forEach will have no documents to iterate over. So you can't detect the absence of results with forEach.
Instead, you can use .empty on the result to check if there are no docs matching that username.
Check the code below.
const userQ = query(
collection(db, "users"),
where("username", "==", username)
);
const queryName = await getDocs(userQ);
if(queryName.empty){
console.log("Username is available");
}
else{
console.log("Username is already taken.");
}
Related
I am importing the data from the currently signed in user in order to manage the entire user profile page and all the associated actions.
On one hand I have the auth.currentUser and on the other I have the USERS collection in the db which stores all the additional data related to that particular user.
Now, my question concerns optimization. What would be the ideal way to get this user's data? Currently I am getting the entire users collection and filtering to get the one that matched the uid from the route params, yet I was told that loading the entire users collection and filtering the one I want to display was less than ideal, that I should rather create a function to get a specific user by a property such as name or id. This is what confuses me, is that not essentially what I am doing by filtering the users collection? How else would it be best to get that user's info? By creating this function in the Store and not in the component itself?
Currently it's looking like this:
UserPage.vue
const storeUsers = useUserStore();
const users = storeUsers.users;
const route = useRoute();
const id = route.params.id;
const userData = computed(() => {
return users.find((u) => u.uid == id);
});
Any way to optimize this would be appreciated.
*Adding a screenshot of the Firestore console (data model):
Your code is loading every document from the users collection into your application code, and then choosing there which single document you are actually interested in. Since you pay for every document read from the database, and you (and your users) pay for all bandwidth that is used, this is wasteful - especially as you start adding more users to the collection.
Instead you should use a query to read only the document(s) you are interested in from the database into your application code. Read the documentation for examples for all supported SDK versions.
finally solved it using a query as suggested. I am triggering the getUserInfo action whenever a user signs in and then assigning it to a pinia state called currentUserData:
AUTH STORE
async getUsers() {
onSnapshot(userCollectionRef, (querySnapshot) => {
let users = [];
querySnapshot.forEach((doc) => {
let user = {
did: doc.id,
...doc.data(),
};
this.users.push(user);
});
});
},
getUserInfo(userCredential) {
const q = query(
userCollectionRef,
where("uid", "==", userCredential.user.uid)
);
onSnapshot(q, (snapshot) => {
let currentUserData = [];
snapshot.docs.forEach((doc) => {
currentUserData.push({ ...doc.data(), id: doc.id });
});
this.currentUserData = currentUserData;
});
}
I am receiving the following error when attempting to retrieve a document from a firestore database using a query. The error is: Uncaught FirebaseError: Function Query.get() requires its first argument to be of type object, but it was: an array.
As I expected it return an array of documents (as per Google documentation) I am confused by the message? Can someone tell me where I am going wrong?
if (email) {
var db = firebase.firestore();
db.collection("guarantees").where("customer.email", "==", email)
.get().then((snap) => {
let doc = snap.docs[0];
//....
It's hard to tell what the issue, but it looks like email is an array and if you want the query to search an array, maybe you can use the following code:
if (email) {
var db = firebase.firestore();
db.collection("guarantees")
.where("customer.email", "in", email)
.get()
.then((snap) => {
let doc = snap.docs[0];
console.log(doc.data());
});
//....
or check the type of email isn't an object and use your original code.
check out these doc's they are super helpful.
I know firestore doesn't allow inequality statements in .where() queries and I should instead chain > and < queries, but I don't know how this will work in my case.
In my react native app, I want to select some users who have not been already added by the user. After getting an array of all the users the current user has already added as so:
var doc = await firebase
.firestore()
.collection(`users/${currentUser.uid}/user_data`)
.doc("friends")
.get();
var friends = doc.data()
I then want to choose some users who have not been added by the current user as so:
var docs = await firebase
.firestore()
.collection("users")
.limit(10)
.where("username", "not in", friends)
.get();
How would I do this? Thanks
This kind of query is not possible with Firestore. Firestore can only query for things that exists in the indexes that it creates for each field. These indexes can't be queried efficiently for things that don't exist.
See also: Firestore: how to perform a query with inequality / not equals
I am using a Realtime Database to handle some data in a Firebase web app.
In the code hereafter, I want to insert a record in the DB only if fieldOne and fieldTwo aren't going to be duplicated.
dbReference.orderByChild("fieldOne").equalTo(fieldOneVal).once('value')
.then(function(snapshot) {
if (snapshot.exists()) {
alert('This fieldOne has already been used.')
reject();
}
}).then( // What is the correct way to connect this line and the following ??
dbReference.orderByChild("fieldTwo").equalTo(fieldTwoVal).once('value')
.then(function(snapshot) {
if (snapshot.exists()) {
alert('This NAME has already been used.')
reject();
}
// All is now OK.
.... do the final things here .....
}).catch(function(error) {
// An error happened.
alert('This record cannot be inserted.')
});
At this point, I am able to tweak the code to make things work the way I wish. But my issue is that I am not doing things the proper way (I know that due to some messages I can see in the console). The comment in my code shows where I need to know the correct way to connect the two parts.
What is the .... the following ??
For information the DB looks like this:
MyList
+ -M93j....443cxYYDSN
fieldOne: "asdc..."
fieldTwo: "Gkk...."
+ -M94j.........OZS6FL
fieldOne: "afc..."
fieldTwo: "SDFSk...."
The following Promises chaining combined with errors throwing should do the trick.
dbReference
.orderByChild('fieldOne')
.equalTo(fieldOneVal)
.once('value')
.then(function (snapshot) {
if (snapshot.exists()) {
throw new Error('fieldOneExists');
}
return dbReference
.orderByChild('fieldTwo')
.equalTo(fieldTwoVal)
.once('value');
})
.then(function (snapshot) {
if (snapshot.exists()) {
throw new Error('fieldTwoExists');
}
// All is now OK.
//.... do the final things here .....
})
.catch(function (error) {
if (
error.message === 'fieldOneExists' ||
error.message === 'fieldTwoExists'
) {
console.log('This record cannot be inserted');
} else {
console.log('other error');
}
});
However, it would probably be better to use a Transaction for checking the existence of the two values for the fieldOne and fieldTwo fields.
The problem is that the Realtime Database transactions don't work with queries: you need to exactly know the location of the data to be modified (or to be checked for existence/non-existence). So you would need to adapt your data model if it appears that you really need a transaction (which depends on your exact global requirements).
For example you could create database nodes with the concatenation of the values of fieldOne and fieldTwo values and check the existence of such a node in a Transaction. But, again, the feasibility of this approach depends on your exact global requirements, which we don't know.
Try the hasChild() method.
if(snapshot.hasChild('name') {
// ... do stuff !
}
Or,
create a new node in your firebase real-time db named as usernames and add each username in this list. In future before inserting a new username check if it's present in this list
Is there way to check if an email id exists in the AdminDirectory.Users or not? I know that https://developers.google.com/admin-sdk/directory/v1/reference/users/get retrieves all the users, is there a query like exists(from sql) in Google apps script?
The .get() function is used to get an individual user.
To test is the user existis or not you can use .get() in a try catch
This function will return true if the user exists and false if not.
function lookupUser(email){
var isUser
try{
var user = AdminDirectory.Users.get(email);
isUser = true;
} catch (e){
isUser = false;
}
return isUser;
}
If we base the methods in Directory API, there's Users.list which has a 'query' property. The valid queries you can perform are found in Search for users and sure enough there's an 'email' value.
Play around with that and try it in Apps Script's List all users.