Firestore can't get empty docs - javascript

I have collection of documents where the id of the doc is the users id.
Lets call these user documents.
Each "user document" contains a subcollection of chat messages. But not all "user documents" contains any fields (data, other than the subcollection).
I wan't to return all the doc in the collection that don't have any fields, but have a subcollection, but I seems this is not possible?
var allUserDocs = {},
count = 0,
users = firestore.collection("users");
users.get().then(snapshot => {
snapshot.forEach(doc => {
count++;
allUserDocs[count] = doc.data();
});
allUserDocs.count = count;
res.status(200).send(allUserDocs);
})
this code only returns the docs that contains fields, not the docs that only have a subcollection? Is there a way to return all?
How can i get a list of all document ids in the collection? both empty and non-empty ones? or how can I add a field to all the docs without fields if i cant access them?

There is a listDocuments method that retrieves all documents, missing or not, that have a subcollection. Here's the page in the docs that explains it.
Something like this might be what you are looking for:
let collectionRef = firestore.collection('col');
return collectionRef.listDocuments().then(documentRefs => {
return firestore.getAll(...documentRefs);
}).then(documentSnapshots => {
for (let documentSnapshot of documentSnapshots) {
if (documentSnapshot.exists) {
console.log(`Found document with data: ${documentSnapshot.id}`);
} else {
console.log(`Found missing document: ${documentSnapshot.id}`);
}
}
});
You would not care whether the docRef exists or not.
Nevertheless, it does not sound like a good solution to have empty documents. What is the logic you were pursuing with an architecture where users can be empty, but messages underneath them still matter? Maybe if you still need to access them you can add a boolean variable to determine if the user is active or not, instead of leaving a blank document.

Use doc.id
users.get().then(snapshot => {
snapshot.forEach(doc => {
count++;
allUserDocs[doc.id] = doc.data();
});
allUserDocs.count = count;
res.status(200).send(allUserDocs);
})

Related

get values from firestore query

I have this function:
firestore.collection('customers').doc(userID).collection('subscriptions')
.where('status', 'in', ['trialing', 'active']).get()
.then(activeSubscriptions => {
// if this is true, the user has no active subscription.
if (activeSubscriptions.empty === true) {
console.log("line 31")
{signOut(props.history)}
subStatus = "inactive"
}
});
Basically, in firestore, I have a customers collection, a doc with the user id, and then the subscriptions collection in which is created upon a user processing stripe. In the subscriptions collection, it has a doc which is the subscription id, and I have some fields I want to grab. See the attached picture:
I want to grab the current_period_end data so I can put it out on screen. how would I do this?
If you are looking to access fields from a firestore document, you can do it by specifying the field in square brackets.
With a firestore structure like /customer/cus123/subscriptions/sub123 I was able to obtain a timestamp field of sub123 with this code:
let cusRef = db.collection('customer').doc('cus123').collection('subscriptions').doc('sub123');
cusRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
}
else
{
console.log('Name: ',doc.data()['name']);
console.log('Tmsp: ',doc.data()['tmsp123']);
}
});
I hope you find this useful.

_firebase__WEBPACK_IMPORTED_MODULE_10__.usersCollection.doc(...).collectionGroup is not a function

I have a problem like in the title. When I want to download my 'hives' using collectionGroup, this error pops up and I don't know what I can do to make it work.
enter image description here
And my code:
async getHives() {
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collectionGroup('hives')
.onSnapshot(snapshot => {
let hivesArray = [];
snapshot.forEach(doc => {
let hive = doc.data();
hive.id = doc.id;
hivesArray.push(hive);
});
store.commit('setHives', hivesArray);
});
},
A collection group query can't be contained within a specific document - there is no API for that. It can only be performed across the entire database:
firebase.firestore().collectionGroup("hives")
If you want to filter all those documents to only receive certain ones, you can do that just like any other query.
firebase.firestore().collectionGroup("hives")
.where("someField", "==", true)

Firestore retrieve single document by field value and update

I'm trying to retrieve a single document by a field value and then update a field inside it.
When I do .where("uberId", "==",'1234567'), I am getting all the docs with field uberId that matches 1234567.
I know for sure there is only one such document. However, I don't want to use uberId as the document's ID, otherwise I could easily search for the document by ID. Is there another way to search for a single document by a field ID?
So far, reading the docs, I could see this:
const collectionRef = this.db.collection("bars");
const multipleDocumentsSnapshot = await collectionRef.where("uberId", "==",'1234567').get();
Then I suppose I could do const documentSnapshot = documentsSnapshot.docs[0] to get the only existing document ref.
But then I want to update the document with this:
documentSnapshot.set({
happy: true
}, { merge: true })
I'm getting an error Property 'set' does not exist on type 'QueryDocumentSnapshot<DocumentData>'
While you may know for a fact there's only one document with the given uberId value, there is no way for the API to know that. So the API returns the same type for any query: a QuerySnapshot. You will need to loop over the results in that snapshot to get your document. Even when there's only one document, you'll need that loop:
const querySnapshot = await collectionRef.where("uberId", "==",'1234567').get();
querySnapshot.forEach((doc) => {
doc.ref.set(({
happy: true
}, { merge: true })
});
What's missing in your code is the .ref: you can't update a DocumentSnapshot/QueryDocumentSnapshot as it's just a local copy of the data from the database. So you need to call ref on it to get the reference to that document in the database.
async function getUserByEmail(email) {
// Make the initial query
const query = await db.collection('users').where('email', '==', email).get();
if (!query.empty) {
const snapshot = query.docs[0];
const data = snapshot.data();
} else {
// not found
}
}

How do to retrieve all documents in a collection and see if a document exists in firebase Firestore?

Schema:
This is how my schema looks
Current Implementation:
for (let i=0; i<data.length; i++) {
try
{
var ifPresent = db.collection("Safes-Hardware").doc(data[i]['Mac address Check']);
ifPresent.get()
.then(async (doc)=>{
if (!doc.exists)
{
// Do stuff
}
else
{
//Do stuff
}
return { message: "Success is within the palm of our hands." }
}
}
Problem:
Even though this code does the job, for each data in the array I'm doing a lookup, and this results in a socket hang-up.(sometimes)
So I'm thinking I'll get all the documents in the collection in one go, store it locally and look up if a documents exists locally instead of querying the database every time.
Question:
How do I implement this?
You can just use collection("Safes-Hardware").get().then() and you can save the data locally.
let collection = []
db.collection("Safes-Hardware").get().then(function(querySnapshot) {
collection = querySnapshot.map((doc) => ({
id: doc.id,
...doc.data()
}))
});
then you can use collection to search for what you want, maybe like this
data.forEach( doc => {
let x = collection.find(v => v.id === doc['Mac address Check'])
if(x){
//it exists
}else{
// not exists
}
})
But take care you are compromising bandwidth or number of requests with o(n^2) operation in the client side

Need help searching for a value in firestore

I'm new to firestore and I'm making a register page with vue.
Before a new user is made, it has to check if the given username already exists or not and if not, make a new user.
I can add a new user to the database, but I don't know how to check if the username already exists or not. I tried a lot of things and this is the closest I've gotten:
db.collection("Users")
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
if (this.username === doc.data().username) {
usernameExist = true;
}
});
});
Anyone got any ideas?
Link to documentation: https://firebase.google.com/docs/firestore/query-data/queries#simple_queries
You can where this query, which is beneficial to you in multiple ways:
1: Fewer docs pulled back = fewer reads = lower cost to you.
2: Less work on the client side = better performance.
So how do we where it? Easy.
db.collection("Users")
.where("username", "==", this.username)
.get()
.then(querySnapshot => {
//Change suggested by Frank van Puffelen (https://stackoverflow.com/users/209103/frank-van-puffelen)
//querySnapshot.forEach(doc => {
// if (this.username === doc.data().username) {
// usernameExist = true;
// }
//});
usernameExists = !querySnapshot.empty
});

Categories