Map Firestore saving field name - firebase

can you help me? I have a problem to my code coz instead of updating my map value the path changes also
const userId = firebase.auth().currentUser.uid;
const availableRecord = firebase.firestore().collection('orders').doc(this.state.OrderId);
availableRecord.update({
stores: { userId: 'On the way'}
}).then(( res) => {
console.log('Product is set into AVAILABLE')
})
Instead of
the result is

Using the square brackets notation, as follows, should do the trick:
const userId = firebase.auth().currentUser.uid;
const availableRecord = firebase.firestore().collection('orders').doc(this.state.OrderId);
const stores = {};
stores[userId] = 'On the way';
availableRecord.update({ stores }).then(() => {
console.log('Product is set into AVAILABLE');
});
Doing
availableRecord
.update({ stores: { [userId]: 'On the way' } })
also works, as you noted in your comment.

Related

Firestore pagination and Vue

I am trying to create Infinite scrolling pagination with Vuejs and Firestore.
So far I have been able to get the code to work in the sense that it is fetching and showing the data as intended. However when the new query is constructed after scrolling down to the bottom, the original query with the same values loads again.
It seems that I am doing something wrong with the startAfter() method, which is supposed to get the next values in the firestore query.
This is my setup:
setup() {
const latestDoc = ref(null);
const getFoods = ref([]);
onMounted(() => {
runQuery(latestDoc.value);
});
const runQuery = async (doc) => {
let q = query(collection(db, "foods"), orderBy("title"), startAfter(doc), limit(5));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
getFoods.value.push({ ...doc.data(), id: doc.id });
});
};
const loadData = (InfiniteScrollCustomEvent) => {
InfiniteScrollCustomEvent.target.complete();
latestDoc.value = getFoods.value.length - 1;
runQuery(latestDoc.value);
};
return { getFoods, optionsOutline, loadData, latestDoc, runQuery };
},
Can anyone tell me what I am doing wrong?

How to get all items from subcollection Firebase Firestore Vue

How do I get all the comments from the subcollection?
This is mine reusable function to get comments collection.
import { ref, watchEffect } from 'vue';
import { projectFirestore } from '../firebase/config';
const getCollection = (collection, id, subcollection) => {
const comments = ref(null);
const error = ref(null);
// register the firestore collection reference
let collectionRef = projectFirestore
.collection(collection)
.doc(id)
.collection(subcollection);
const unsub = collectionRef.onSnapshot(
snap => {
let results = [];
snap.docs.forEach(doc => {
doc.data().createdAt && results.push(doc.data());
});
// update values
comments.value = results;
error.value = null;
},
err => {
console.log(err.message);
comments.value = null;
error.value = 'could not fetch the data';
}
);
watchEffect(onInvalidate => {
onInvalidate(() => unsub());
});
return { error, comments };
};
export default getCollection;
And this is mine Comments.vue where i passing arguments in setup() function (composition API)
const { comments } = getAllComments('posts', props.id, 'comments');
When i console.log(comments) its null, in snapshot doc.data() is good but somehow results too is empty array even if i push doc.data() to results array and pass it to comments.value.
Can someone help me how to get that subcollection?
This is my Comment.vue component
export default {
props: ['id'],
setup(props) {
const { user } = getUser();
const content = ref('');
const { comments } = getAllComments('posts', props.id, 'comments');
const ownership = computed(() => {
return (
comments.value && user.value && user.value.uid == comments.value.userId
);
});
console.log(comments.value);
}
return { user, content, handleComment, comments, ownership };
},
};
const getCollection = (collection, id, subcollection) => {
const comments = ref(null);
const error = ref(null);
// Firestore listener
return { error, comments };
}
The initial value of comments here is null and since Firebase operations are asynchronous, it can take a while before the data loads and hence it'll log null. If you are using comments in v-for then that might throw an error.
It'll be best if you set initial value to an empty array so it'll not throw any error while the data loads:
const comments = ref([]);
Additionally, if you are fetching once, use .get() instead of onSnapshot()

PROBLEM Getting a single field in a document in Firebase Firestore

I'm trying to do a Cloud Function in Firebase. Initially, I read my document. Then I would take two fields "a" and "b", from this document. Then I want to set another field of my doc ('rank') as the sum of 'a' and 'b'. I can't find a solution!
I want to take only the fields "a" and "b" from my document. Save them in variables. And use those variables to do the sum, and set the result in "rank" field.
I tried:
var data = doc.data()
a = data.a
b = data.b
but it doesn't work.
Code:
export const daicazzo = functions.https.onRequest((request,response)=>{
const store = admin.firestore();
//var b;
store.collection('questions').doc('LD92BBDOihAC3fHDyoV').get().then(doc =>{
if(doc.exists){
response.send(doc.data())
}
else{
response.send("Nothing")
}
}).catch(reason => {
console.log(reason)
response.send(reason)
})
store.collection('questions').doc('LD92BBDOihAC3fHDyoV').set({
rank: //a+b
})
.then(function() {
console.log("done");
})
.catch(function(error){
console.log("Error:",error);
});
});
Should do the work (might be some better solutions)
const store = admin.firestore();
export const daicazzo = functions.https.onRequest(async (request,response)=>{
const questionRef = store.doc(`questions/${LD92BBDOihAC3fHDyoV}`)
const doc = await questionRef.get()
const foundDoc = doc.exists
if (foundDoc) {
// getting both key/value pairs from doc object
const {a, b} = doc.data()
const rank = a + b // whatever is your logic...
// saving the rank in the same document
await questionRef.update({rank}) // or questionRef.set({rank}, {merge: true})
if you want to send back the doc with the updated rank without making another read, assuming you handle errors:
const { id } = doc
const updatedDoc = { ...doc.data(), id, rank }
return response.send(updatedDoc)
} else {
return response.send("Nothing")
}
});

How to update document in firebase cloud function

In my cloud function I want to update my document from 'dashboard' collection when a new student added to 'students' collection.
const getActiveStudents = () => {
return db.collection('/students/').where('status', '==', true).get().then(
snapshot => {
let studentsCount = snapshot.docs.length;
db.collection('/dashboard/').where('type', '==', 'students').get().then(
result => {
if (result.docs.length === 0) {
db.collection('dashboard').add({
count: studentsCount,
type: 'students',
label: 'Active students'
});
}else {
result.docs[0].ref.update({
count: studentsCount,
type: 'students',
label: 'Active students'
});
}
return result;
}
).catch(error => {
console.log(error);
});
return snapshot;
}
).catch(error => {
console.log(error);
})
}
exports.onChangesInStudents = functions.firestore.document('/students/{studentId}').onWrite(event => {
getActiveStudents();
return;
});
When I add a new student, instead of updating document it adds a new document to my 'dashboard' collection.
How should I organize my code in order to properly update the quantity of students.
as #Doug mentioned, iterating over the entire collection is too heavy. instead you can stream the query results and iterate over keys, using query.stream().
to access and update a single field in a document, first retrieve the document by its ID with doc(), then use update() while specifying the field.
here's an example of implementation based on your scenario.
package.json
{
"dependencies": {
"firebase-admin": "^6.5.1",
"firebase-functions": "^2.1.0"
}
}
index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const studentsRef = admin.firestore().collection('students');
const dashboardRef = admin.firestore().collection('dashboard');
exports.addStudent = functions.firestore
.document('students/{studentId}')
.onCreate((snap, context) => {
var newStudent = snap.data();
console.log('New student in collection: ', newStudent);
var activeCount = 0;
studentsRef.where('status', '==', true).select().stream()
.on('data', () => {
++activeCount;
}).on('end', () => {
dashboardRef.where('type', '==', 'students').get()
.then(querySnap => {
if (querySnap.docs[0].data().count == activeCount){
console.log('No new active student: ', querySnap.docs[0].data());
} else {
console.log('New active count: ', activeCount);
console.log('Student Dashboard before update: ', querySnap.docs[0].id, '=>', querySnap.docs[0].data());
dashboardRef.doc(querySnap.docs[0].id).update({
count: activeCount
});
console.log('Active student count updated: ', querySnap.docs[0].data().count, '=>', activeCount);
};
});
});
return null
});
gcloud
gcloud functions deploy addStudent \
--runtime nodejs8 \
--trigger-event providers/cloud.firestore/eventTypes/document.create \
--trigger-resource "projects/[PROJECT_ID]/databases/(default)/documents/students/{studentId}"
When a function is triggered, you might want to get data from a document that was updated, or get the data prior to update.
You can get the prior data by using change.before.data(), which contains the document snapshot before the update.
Similarly, change.after.data() contains the document snapshot state after the update.
Node.js
exports.updateUser = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
// Get an object representing the current document
const newValue = change.after.data();
// ...or the previous value before this update
const previousValue = change.before.data();
//...therefore update the document as.
admin.firestore().collection('user').doc(docId).update(snapshot.after.data());
});
Reference:-
https://firebase.google.com/docs/functions/firestore-events

Firebase - Firestore - get key with collection.add()

I am facing a problem with the new Firestore from Firebase.
Situation: I have a collection('room')
I create room with collection('room').add(room)
What I'm trying to do: I need to update a room.
For this, I use: collection('room').doc(ROOM_ID).update(update)
So I need to add ROOM_ID in the document in my collection:
|room
ROOM_ID
id:ROOM_ID,
someContent: ForTheQuery
Is there a possible way to achieve that?
An alternative is to create myself a generated ID with:
collection('room')
.doc(someId)
.set({
id: someId,
someContent: ForTheQuery
});
but i want to avoid it.
You can use doc() to create a reference to a document with a unique id, but the document will not be created yet. You can then set the contents of that doc by using the unique id that was provided in the document reference:
const ref = store.collection('users').doc()
console.log(ref.id) // prints the unique id
ref.set({id: ref.id}) // sets the contents of the doc using the id
.then(() => { // fetch the doc again and show its data
ref.get().then(doc => {
console.log(doc.data()) // prints {id: "the unique id"}
})
})
ANGULARFIRE:
get ID before add database:
var idBefore = afs.createId();
console.log(idBefore );
ANDROID FIRESTORE:
String idBefore = db.collection("YourCol").document().getId();
Firebase Javascript SDK:
Just use .id to get the key, here is an example using async/ await :
const KEYID = async() => (await fs.collection("testing").add({ data: 'test'})).id;
You can get the ID from the created document by using collection.ref.add(your item without id) and the response (res) will contain the new document reference created with the ID inside it. So get the ID by simply doing res.id.
createOne(options: { item: any, ref: AngularFirestoreCollection<any> }) {
const promise = new Promise((resolve, reject) => {
if (options.item) {
// Convert object to pure javascript
const item = Object.assign({}, options.item);
console.log('dataService: createOne: set item: ', item);
options.ref.ref.add(item)
.then((res) => {
console.log('dataService: createOne success: res: ', res);
resolve(res);
}).catch(err => {
console.error('dataService: createOne: error: ', err);
reject(err);
});
} else {
console.log('dataService: createOne: wrong options! options: ', options);
reject();
}
})
return promise;
}

Resources