How can I get the document id of a firestore document after successfully fetching the document. I am fetching user data from firestore collections like this
const ref = await db.collection('users').where('phone', '==', phone)
.where('password', '==', password).get();
I have a valid document after executing this query.
const data = ref.docs[0].data();
How can I get the auto generated document id? I tried data.id and data.path, it is returning undefined.
How can I access the auto generated id?
In my code, it was actually trying to get the data id, instead of document id
i got the document id by adding const docRefId = ref.docs[0].id;
In addition to Sony's answer, you can get the document reference as well:
const docRefId = ref.docs[0].ref;
Related
Articles I've read/tried before:
Firestore search array contains for multiple values
Performing a complex query with firestore v9
Firestore collection to array of objects with Firebase v9
FirebaseError: Expected type 'Tc', but it was: a custom Ac object,
https://softauthor.com/firebase-firestore-get-document-by-id/
I have a Firestore that looks like this
The current feature I'm trying to implement is a block list. Whenever you go to the person's profile, you click block, and the person doing the blocking's UID is stored as the doc id and the blocked user's id is added to the "blockedUserId" array
The home page displays all the posts and I've been trying to filter the displayed posts to not include posts from any of the users in that "blockedUserId" array
How do I go about doing this correctly?
Here is the attempted code
query(
collection(getFirestore(fireApp), "posts"),
orderBy("uid"),
where(
"uid",
"not-in",
doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2")
)
Firestore queries can only filter on values in the document itself, and values you explicitly pass in to the query. Your doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2") creates a DocumentReference, so the query returns documents from posts that don't contain that document reference.
What you want to do instead is:
Load the blocked UIDs
Pass them to the query
So in code:
const myRef = doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2");
const myDoc = await getDoc(myRef);
const blocked = myDoc.data().blockedUserId;
const q = query(
collection(getFirestore(fireApp), "posts"),
orderBy("uid"),
where(
"uid",
"not-in",
blocked
)
)
// TODO: call getDocs or onSnapshot on q
I'm trying to get the real-time document fields (text and timeStamp) to be displayed from the "first" collection in firestore collection, with the use of onSnapshot. I can verify that the snapshot realtime updation is working, on addition of a new document, it does shows an update. But I cannot access the text and timeStamp in the document.
onSnapshot(collection(db, 'first'), (snapshot) => {
console.log(snapshot.text, snapshot.timeStamp);
});
It just shows undefined to me. Also, I just want to access this database, db only when the user is authenticated. So is there a way to check if the user is authenticated?
To get the data from a document snapshot, you need to call data() on it. In addition, since you're reading an entire collection, you get back a query snapshot that can contain multiple documents, which you also need to handle.
So:
onSnapshot(collection(db, 'first'), (querySnapshot) => {
querySnapshot.docs.forEach((docSnapshot) => {
console.log(docSnapshot.data().text, docSnapshot.data().timeStamp);
})
});
See the documentation on getting data from Firestore and on reading all documents from a collection for more examples like this.
I'm trying to fetch sub-collection documents from my firestore database.
Collection Imgs:
My current code:
const fetchHighlight =async()=>{
const Highlight = []
const HighlightDbId = await
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').collection('4C4kd2QnaQhcp9knexkW').get()
console.log(HighlightDbId)
}
React.useEffect(()=>
{
fetchHighlight ()
}, [])
You forgot to fetch your query at the end of your chain, and the subcollection 4C4kd2QnaQhcp9knexkW does not exist, it's the id of a document in the subcollection you're trying to access. The right subcollection ID was hBYWvZ3KN3NLLrucTpryETQZnz2.
To sum up, you could go this way:
const yourDocument = (await db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk')
.collection('hBYWvZ3KN3NLLrucTpryETQZnz2').doc('YOUR_DOC_ID').get()).data()
or this way:
const yourDocument = (await db.collection('highlights/2SCS2S0JnzngWEiYkHNk/hBYWvZ3KN3NLLrucTpryETQZnz2')
.doc('YOUR_DOC_ID').get()).data()
Edit
If you want to fetch only the first document of the subcollection you can go this way:
const yourDocument = (await db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk')
.collection('hBYWvZ3KN3NLLrucTpryETQZnz2') // subcollection ref
.orderBy("createdAt", "asc") // index
.limit(1) // limit the size of your response
.get()) // send the request and wait for it (you could also use '.then()' here)
.docs[0] // get the first doc of the array
.data() // retrieve the doc's data use `.id` instead if you want its id
And if you want to get the first subcollection of a doc you should go this way with the listCollections method:
const subcollectionId = (await db
.doc('highlights/2SCS2S0JnzngWEiYkHNk')
.listCollections())[0] // retrieve the first subcollection `.id`
Note that this only works with the node.js library, if you're attempting to do your query fore the front-end, it will fail. Then you should simply put a reference of your subcollection inside your parent doc by an update when creating your subcollection in the first place:
// const HighlightDbId = creating you subcollection
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').update({
subcollection: HighlightDbId
});
And simply retrieve the field subcollection when you need to fetch data from its subcollection.
I fixed this problem by adding the last doc :
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').collection('4C4kd2QnaQhcp9knexkW').doc('XXXXXXXX').get()
I can't find how to create a new document without any fields, but one subcollection - messages (and this message collection would have some fields).
This is what I want to do. But I don't want to create subcollection in document which already exist. I want to create new document and subcollection in it.
Honestly I stopped on that :
let chatRef = db.collection("chat_event").add({
})
This answer will greatly help.
let chatRef = db
.collection("chat_event").document("chat1")
.collection("messages").document("message1");
If you don't want to hardcode the parent document's id or if you want a firestore generated id. Then get the id first from firestore's createId() function.
let chatEventId = db.createId();
let chatRef = db
.collection("chat_event").document(chatEventId)
.collection("messages").document("message1");
You could still use auto-generated id for the subcollection's document:
let chatEventId = db.createId();
let messageId = db.createId();
let chatRef = db
.collection("chat_event").document(chatEventId)
.collection("messages").document(messageId);
Note that firestore's autogenerated IDs are entirely random and consequently the documents are not stored in any chronological order. If you will in anyway need some ordering, you could add timestamps to those documents either when you insert data or you update the document with the timestamp info.
docRef.update({
timestamp: firebase.firestore.FieldValue.serverTimestamp()
});
With that, you can order chronologically both in the console and in your own queries.
Check out this answer for more information on auto-generating IDs
My Cloud Firestore looks like this:
users
├────random_id_1───{name, email, ...}
├────random_id_2───{name, email, ...}
...
└────random_id_n───{name, email, ...}
I want to update a document of users given I have an unique identifier for it that is NOT the random id of the document (suppose, for example, the name is unique and I want to use it as identifier).
How can I update a document identifying it by a field of it?
Firestore can only update documents for which it knows the complete reference, which requires the document ID. On your current structure, you will have to run a query to find the document. So something like:
firebase.firestore().collection("users")
.where("name", "==", "Daniel")
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(document) {
document.ref.update({ ... });
});
});
If you have another attribute that is unique, I'd always recommend using that as the IDs for the documents. That way you're automatically guaranteed that only one document per user can exist, and you save yourself having to do a query to find the document.