I'm looking for the best way to:
1. query for one single result, or
2. extract the first result from the query
tried: collection[0] and collection.pop() or collection.shift() and nothing works
I really don't like the code i'm using, but it works...
export const findUserByEmail = email => {
return firestore()
.collection('users')
.where('email', '==', email.toLowerCase())
.get()
.then(collection => {
console.log(collection)
let user
collection.forEach(doc => user = doc.data())
return user
})
}
Your query returns a QuerySnapshot (see docs). You can access the docs as an array via the docs property; each doc has a data() method:
export const findUserByEmail = email => {
return firestore()
.collection('users')
.where('email', '==', email.toLowerCase())
.get()
.then(querySnapshot => {
if(!querySnapshot.empty) {
const user = querySnapshot.docs[0].data()
// rest of your code
}
})
}
Firestore with Flutter solution:
await FirebaseFirestore.instance
.collection('users')
.where('userId', isEqualTo: loggedInUserId)
.get()
.then((querySnapshot) {
List listData = querySnapshot.docs.toList().map((item) {
// to fetch list of all documents information
return item.data();
}).toList();
if (querySnapshot.docs.length > 0) {
// to fetch first document information
_mappedUserInfo = querySnapshot.docs[0].data();
}
print("listData: ${listData.toString()}");
print("_mappedUserInfo: ${_mappedUserInfo.toString()}");
}).catchError((e) {
print('data error: $e');
});
Result:
Fetched List of documents:
listData: [{name: null, addedOn: Timestamp(seconds=1623663004, nanoseconds=581000000), email: john.doe2021#mailinator.com, phoneNumber: null, userId: yRARGJOaAbM78MW5OBlVEB3VyKkr, lastSignInOn: Timestamp(seconds=1623663004, nanoseconds=581000000), photoURL: null}]
Fetched single document:
_mappedUserInfo: {name: null, addedOn: Timestamp(seconds=1623663004, nanoseconds=581000000), email: john.doe2021#mailinator.com, phoneNumber: null, userId: yRARGJOaAbM78MW5OBlVEB3VyKkr, lastSignInOn: Timestamp(seconds=1623663004, nanoseconds=581000000), photoURL: null}
It worked for me. I hope, this will help you.
tried: collection[0] and collection.pop() and nothing works
Those 2 in order means:
collection[0] - access the first element of an array
collection.pop() - pop get's rid of the last
element of an array
Maybe based on your code logic, you should try: collection[0].data(); as by using collection[0] you access the first element, but from your existing code you need to call .data() to extract it.
forEach does simply access to the whole content of collection.
Whilst collection.pop() is just not the proper tool for the job in this case.
Related
I have some code that gets a collection reference to the users collection and then queries an animeID field whether it contains a certain value or not. I want to change this and only query inside the document with the id i pass. So if you look at the picture of my firestore you can see that i have two documents inside the users collection each with their unique id. I want to query for the animeID field only in the document that i want. Not all the documents as it does right now. How would i go about doing this? I have tried using doc and then passing in the id of the document but i don't think query works on doc as it gives me an error. Thanks
const docRef = collection(db, 'users')
const q = query(docRef, where('animeID', 'array-contains', parseInt(id)))
onSnapshot(q, (snapshot) => {
let results = []
snapshot.docs.forEach((doc) => {
results.push({...doc.data(), id: doc.id})
})
if(results.length > 0){
console.log(true)
}
else{
console.log(false)
}
}, (error) => {
console.log(error)
})
Firestore structure:
You need to do as explained in the doc:
import { doc, getDoc } from "firebase/firestore";
const docRef = doc(db, "users", "dbmbEiR6....");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const animeID = docSnap.data().animeID;
// Do whatever you want with animeID
// E.g. log its value:
console.log(JSON.stringify(animeID));
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
So you don't need to declare a Query in this case. Just declare a DocumentReference and use the getDoc() method.
I'm currently using Firestore/Vue.js with Vuefire support.
The Firestore DB has just one collection with a couple of users inside:
Users
001
name: Jack
uid: {Firebase auth ID}
org_id: 123
002
name: Frank
uid {Firebase auth ID}
org_id: 456
in the Vue component, I try to query the DB to get the first user using the auth ID (which is currently stored in a Vuex Store)
<script>
import { db } from "../main.js";
export default {
data() {
return {
items: [] // to be used later
};
},
created() {
this.getServices();
},
methods: {
getServices() {
console.log(this.$store.state.user.uid);
db.collection("users")
//.doc("001")
.where("uid", "==", this.$store.state.user.uid)
.get()
.then((snapshot) => {
console.log(snapshot);
if (snapshot != null && snapshot.data != null) {
const user = snapshot.data();
// do something with document
let org_id = user["org_id"];
console.log("org id:" + org_id);
} else {
console.log("No data returned!");
}
});
},
},
};
</script>
the code always returns an empty snapshot. Checks I have performed:
accessing the document directly using its doc ID works
this.$store.state.user.uid is correctly set
hard-coding the uid in the where clause gives the same error
I'm a total beginner but it looks to me the where clause is not working.
Since, with db.collection("users").where("uid", "==", this.$store.state.user.uid) you define a Query, the snapshot Object is actually a QuerySnapshot and not a DocumentSnapshot.
So snapshot.data != null is always false because a QuerySnapshot does not have such a property. It is also the case for snapshot.data() != null => it is always false because a QuerySnapshot does not have such a method.
You should either loop over the QuerySnapshot with the forEach() method or use map on the docs property, as shown in the Vuefire example (see "retrieve a collection"):
db.collection("users")
.where("uid", "==", this.$store.state.user.uid)
.get()
.then((snapshot) => {
const documents = snapshot.docs.map(doc => doc.data())
// do something with documents
})
i am trying to signup and save user info into firestore. Save operation is fine but i want to search that info but nothing happening. Here is my code
Signup
firestore
.collection("users")
.doc(user.userId)
.collection("profile")
.add({ ...user })
.then(() => {
auth.onAuthStateChanged((u) => {
if (u) {
u.updateProfile({
displayName: user.displayName,
});
}
});
});
Fetch All users data
firestore
.collection("users")
.get()
.then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
//doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
});
You should be able to achieve by using a similar code as the below one. It very similar to yours, but with some differences, where we separate the referencing to the database and let the querySnapshot iterates by itself, so the data can be returned. I usually use this format to return data from collections.
var db = admin.firestore()
var usersReference = db.collection("users");
usersReference.get().then((querySnapshot) => {
querySnapshot.forEach((userDoc) => {
console.log(userDoc.id)
var userDocData = userDoc.data()
console.dir(userDocData)
})
})
This should work, so, in case it doesn't return anything, probably your saving opearation is not working properly. This will return both the user's id and the whole data from it.
exports.getref = (oid, successFunc, errFunc) => {
dbconfig.collection('txn')
.where('oid', '==', oid)
.get()
.then(docRef => {
successFunc({
id: docRef.id,
success: true
})
})
.catch(err => {
errFunc({ id: null, success: false })
})
here I want to get document id of my collection where field value oid equals oid . how i can get doc id
When you perform a query with Firestore, you get back a QuerySnapshot object, no matter how many documents match the query.
dbconfig.collection('txn')
.where('oid', '==', oid)
.get()
.then(querySnapshot => { ... })
You have to use this QuerySnapshot to find out what happened. I suggest reading the linked API documentation for it.
You should check to see if it contains any documents at all with the size method, then if it has the document you're looking for, use the docs array to find the DocumentSnapshot with the data. That snapshot will have a DocumentReference property with the id:
if (querySnapshot.size == 1) {
const snap = querySnapshot.docs[0];
console.log(snap.ref.id);
}
else {
console.log("query result in exactly one document");
}
I am trying to get the data of a user to be added to the state based off of a single query search from the user id of the user. I tried to do the single document path, which did not work for me as the firebase.auth().currentUser.uid is different from the doc.id, and the code that I use now is:
firebase.firestore()
.collection("users").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(firebase.auth().currentUser.email);
console.log(doc.data().email;
if (doc.data().email) == firebase.auth().currentUser.email) {
this.setState({
avatar: doc.data().avatar,
name: doc.data().name,
email: doc.data().email
});
}
});
});
While this code works, it is incredibly inefficient as it goes through all the users and compares their email it the current user email. I would like to know if there was a way one could just search for the data without using this method. Any help would be largely appreciated. Thank you in advance!
Try to do something like this and comment if it worked out for you:
firebase.firestore()
.collection("users")
.where('email', '==', firebase.auth().currentUser.email)
.get()
.then((querySnapshot) =>
querySnapshot.forEach((doc) =>
this.setState({
avatar: doc.data().avatar,
name: doc.data().name,
email: doc.data().email
})
)
);