Adding a new field in Firestore - javascript

In firestore, a field is like a column in mysql. How can I add a field in every existing document in Firestore using Javascript?
I am interested to add an empty array field in every document.
I thought this is common but somehow I could not find any relevant info.
const firebase = require("firebase");
require("firebase/firestore");
firebase.initializeApp({
apiKey: "XXXX",
authDomain: "xxxx",
projectId: "xxxx"
});
var db = firebase.firestore();
function getMyDocs() {
const snapshot =
firebase.firestore().collection('testusers').get()
return snapshot.docs.map(doc => {
db.collection("testusers").doc(doc.id).update({
title: "Testing"
})
});
};
getMyDocs();
This is a nodejs code but I am getting TypeError: Cannot read property 'map' of undefined

You have to fetch all docs and update each one seperatly.
JS Code:
async getMyDocs() {
const snapshot = await db.collection('myCollection').get()
return snapshot.docs.map(doc => {
db.collection("myCollection").doc(doc.id).update({myNewField:"fieldValue"})
});
}

Firestore is nosql.There are no columns or rows.
Instead, you store data in documents, which are organized into collections.
Each document contains a set of key-value pairs. The structure is dynamic.
You can think it like a big json object.

Related

I have a question about Cloud Firestore V9 and using React Js. In one of my docs, there is a map. How do I access this map?

There's a function named getSomethingTEST that I'm using to get the data. Then I have a 'temporary' button onPress={getSomethingTest}, but probably its going to be a useEffect not a button. Later I was going to set my state var "dataFB" to the tempStore array.
But my issue is... I don't know how... So I tried to console.log my results of tempStore. And I got this.. the results in console Which I believe is a nested object inside of an array. So I tried some basic things like tempStore[0].name but its of course undefined. Also I wasn't sure how to reference a key of an object that has a space in it. For this example it was "Asem Jawa".
const firebaseApp = initializeApp({
apiKey: "Hidden",
authDomain: "Hidden",
projectId: "Hidden",
});
const db = getFirestore();
const col_p = collection(db, "WNA-Pasteur");
const docRef = doc(db, "WNA-Pasteur", "branchData");
const [dataFB, set_dataFB] = useState([]);
async function getSomethingTEST() {
const tempStore = [];
const docSnap = await getDoc(docRef);
tempStore.push(docSnap.data());
console.log(tempStore);
}
You are fetching a single document and docSnap.data() is an object containing that document's data. You don't have to push it an array that way.
async function getSomethingTEST() {
const docSnap = await getDoc(docRef);
console.log(docSnap.data().name)
}
This should log the name but in your case, you don't have a property name in your object so it'll be undefined.
I wasn't sure how to reference a key of an object that has a space in it.
You can use brackets notation:
console.log(docSnap.data()["Asem Jawa"] || "Field missing")

Getting previous data in firebase 9.0.0 with onSnapshot trigger

I am using firebase and I am trying to get the previous value of the updated data using 'onSnapshot' method but I couldn't find a way. I know that before version 9 of firebase trigger functions like 'onUpdate' were returning a change object and we were able to reach to both old and new data from that change object but I couldnt figure out a way in the SDK 9 of firebase. I would appreciate if anyone could help me out.
Here is my code snippet:
import { getFirestore, collection, doc, onSnapshot, query } from 'firebase/firestore'
import { initializeApp } from 'firebase/app';
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
/**
* Trigger function that fires on update of any document on cafe collection
*/
export const onUpdate = async () => {
const cafeCollection = collection(db, 'cafes');
const q = query(cafeCollection);
onSnapshot(q, (snapshot) => {
let changesArr = snapshot.docChanges();
if(changesArr.length == 1){
let changes = changesArr[0];
console.log(changes.type); // added-modified-removed
console.log(changes.doc.id); // id of the updated doc
console.log(changes.doc.data()); // newly updated data
}
})
}
I know that before version 9 of firebase trigger functions like 'onUpdate' were returning a change object
A change object is only available in Cloud Functions, as shown in the documentation on Writing Cloud Firestore-triggered functions. It is not (nor ever was) available in the client-side SDKs.
If you want to compare the current and previous snapshot, you will have to introduce a variable where you keep the previous snapshot yourself.

need help accessing Firestore sub-collection?

I'm a novice when it comes to coding (started teaching myself ~year ago), any help will be much appreciated, thank you in advance.
I saw that there is 3-4 other post on stack overflow on how to access Firestore's sub-collections.
I tried them all and had no luck, hence why I'm posting this as a new question.
right now I have my data set is up as: collection/document.array. And that was fine till now because I just needed to read that data from the array to draw it out in my little React project with .reduce and .map and push new data to that array on input.
this is the code I have right now for getting data from Firestore:
--- in firebase.js ----------------------------------------------------------------------
export const fire = firebase.initializeApp(config);
export const db = fire.firestore()
_________________________________________________________________________________________
--- in events-context.js ----------------------------------------------------------------
const fetchEvents = async () => {
try {
const data = await db.collection('events').get();
setEvents(data.docs.map(doc => ({ ...doc.data(), id: doc.id })));
} catch ({ message }) {
alert(`Error # fetchEvents, Error:${message}`);
}
};
But now I want to add edit and a remove feature, but in order to do that, I need to carry out my array of data into a sub-collection so each individual element from that array had its own id so that I could later target it. so it needs to be set up something like this: collection/document/sub-collection
To access a document inside a collection, you must know the document ID from another source. This can be done by managing the names inside an array of strings or maps that you can then process within your app per your design.
For example: once created, you will have a snapshot of the reference of which you can store the document id inside the parent document:
db.collection("events").doc(id).update({
payers: firebase.firestore.FieldValue.arrayUnion(paySnapshot.ref.id)
})`
Once you have this information, you can append it to the relevant document path using one of the following techniques.
db.collection("events").doc(id).collection("payers").doc(pay_id).get()
db.doc(\events/${id}/payers/${pay_id}`).get()`
I strongly advise against using .get() on a collection without limit() and where() conditions to reduce the reads that can occur.
Try this, it works for me :)
Insert data >>>
const q = query(collection(this.fire, "events"));
const querySnapshot = await getDocs(q);
const queryData = querySnapshot.docs.map((details) => ({
...details.data(),
id: details.id,
}));
console.log(queryData);
queryData.map(async (v, id) => {
await setDoc(doc(this.fire, `events/${auth}/more`, events.title), {
'title': events.title,
'uid': auth,
//your data here
})
})
Read Data >>>
const querySnapshot = await getDocs(collection(this.fire,
`/events/${auth}/more/`)); querySnapshot.forEach((doc) => { //
doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data()); });
return querySnapshot;

How to get the unique id (key) of a document in Firebase database collection?

I am trying to fetch the documents of a collection in my React-Native app but I dont know how to fetch them by ID (key).
P.S: I dont have any field called unique id or id inside the document but as I have understood, the unique id is the auto-generated key when I create a document which stands as the name of that document (20 characters id).
This is how I fetch all the fields inside a document:
var ref = firebase.firestore().collection('discounts')
.orderBy('rest_id')
EDIT:
getDiscounts = () => {
try {
this.setState({
loading: true
})
var ref = firebase.firestore().collection('discounts')
.orderBy('rest_id')
.limit(this.state.limit)
ref.onSnapshot((querySnapshot => {
var discounts = querySnapshot.docs.map(document => document.data());
var lastVisibleDiscount = discounts[discounts.length - 1].rest_id;
this.setState({
discounts: discounts,
lastVisibleDiscount: lastVisibleDiscount,
loading: false,
});
}));
}
catch (error) {
console.log(error);
}
}
To print the keys of the documents in the collection in the order of the value of their rest_id field, you can do something like this:
firebase.firestore().collection("discounts").orderBy('rest_id').get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id);
});
});
This is an almost literal copy of the code in the documentation on getting all documents from a collection, so I recommend spending some time there.
You can use (using await/async)
const ref = await ref.get()
It will have an array called docs that you can map over to get the id and data of the document:
const data = ref.docs.map(doc => {return {id: doc.id, data: doc.data()} })

Timestamp not working with firebase-functions-test

I'm using firebase-admin 8.6.0 and firebase-functions-test 0.1.6 which has support for Firestore Timestamps in testing (as of 0.1.5 https://github.com/firebase/firebase-functions-test/releases) but am still receiving an error message when trying to use them with test.firestore.makeDocumentSnapshot.
Can someone help me understand the error in my implementation?
import * as admin from 'firebase-admin';
admin.initializeApp();
const db = admin.firestore();
const settings = { timestampsInSnapshots: true};
db.settings(settings);
const timestamp = admin.firestore.FieldValue.serverTimestamp();
const testingTimestamp1 = admin.firestore.Timestamp.now();
const testingTimestamp2 = admin.firestore.Timestamp.fromDate(new Date);
import * as TestFunctions from 'firebase-functions-test';
const firebaseConfig = {
databaseURL: 'https://...HIDDEN...',
projectId: '...HIDDEN...',
storageBucket: '...HIDDEN...appspot.com',
}
const test = TestFunctions(firebaseConfig, 'service-account-dev.json');
const data({
timestamp,
testingTimestamp1,
testingTimestamp2,
});
const snap = test.firestore.makeDocumentSnapshot(data, path);
const wrapped = test.wrap(processImport);
await wrapped(snap, {params: testParams});
I can't get any of the three timestamp options to work. The latter one I tried learning from #the0rem in https://github.com/firebase/firebase-functions-test/pull/28 but to no avail. I always receive this error:
Cannot encode [object Object]to a Firestore Value. Local testing does not yet support Firestore geo points.`
I was excited when I saw your question because I just faced the same issue. Anyway, here is how I finally solved it. This is the JSON data that I saved from my Firestore database:
const customer = {
username: "A8tAz6wdtucMNKvWSgDkx4bquc2",
timestamp: {
_seconds: 1578762627,
_nanoseconds: 828000000
},
role: "user"
};
Note that timestamp is just a plain object with two properties: _seconds and _nanoseconds. This is where the error "Cannot encode [object Object]to a Firestore Value." comes from i.e. the data object, customer, contains another object, timestamp, which Firestore is unable to parse. What we do to solve this is to make sure that timestamp is not a plain object but an instance of admin.firestore.Timestamp. And here is how you do that:
const seconds = customer.timestamp._seconds;
const nanosecs = customer.timestamp._nanoseconds;
// create a new Timestamp object passing in the required constructor arguments
const properTimestamp = new admin.firestore.Timestamp(seconds, nanosecs);
customer.timestamp = properTimestamp; // update the timestamp reference in your data object
// Now you can do this
test.firestore.makeDocumentSnapshot(customer, '/users/A8tAz6wdtucMNKvWSgDkx4bquc2')
Now if you do console.log(customer); you will see that the timestamp object is an instance of admin.firestore.Timestamp, here is the console output:
// OUTPUT
{
username: 'A8tAz6wdtucMNKvWSgDkx4bquc2',
timestamp: Timestamp { _seconds: 1578762627, _nanoseconds: 828000000 },
role: 'user'
}
PS: I got the answer by checking how Firebase was trying to parse the values/objects in the data. Here is where the parsing was failing and the exception was being thrown (in the file: ../node_modules/firebase-functions-test/lib/providers/firestore.js:165:15):
if (val instanceof firebase_admin_1.firestore.Timestamp) {
return {
timestampValue: val.toDate().toISOString(),
};
}

Categories

Resources