Here is my data:
I want to iterate through each event_prod in event_prods and go to the eventGroups subcollection. Once in that sub-collection, I want to loop through each eventGroup in eventGroups and get doc data.
Here's my code thus far:
async function getAllEventGroups() {
let eventGroups = []
try {
let eventProducerRef = await db.collection('event_prods')
let allEventProducers = eventProducerRef.get().then(
producer => {
producer.forEach(doc => console.log(doc.collection('eventGroups'))
}
)
} catch (error) {
console.log(`get(): there be an error ${error}`)
return []
}
return eventGroups
}
Obviously, it doesn't do what I want, but I can't figure out how to get access to the eventGroups subcollection. Calling 'collection()' on 'doc' is undefined. Can someone please help fix this? By the way, I don't care if this requires two (or more) queries as long as I don't have to bring in data I will never use.
Edit: this is not a duplicated because I know the name of my subcollection
You call the .collection on the QueryDocumentSnapshot. This methods doesn't exist there. But as the QueryDocumentSnapshot extends DocumentSnapshot you can call ref on it to get the reference to the requested document.
```
let allEventProducers = eventProducerRef.get().then(
producer => {
producer.forEach(doc => console.log(doc.ref.collection('eventGroups')) // not the ref here
}
)
eventProducerRef is a CollectionReference. The get() method on that yields a QuerySnapshot, which you are storing in producer. When you iterate it with forEach(), you are getting a series of QueryDocumentSnapshot objects, which you're storing in doc. QueryDocumentSnapshot doesn't have a method called collection(), as you are trying to use right now.
If you want to reach into a subcollection of a document, build a DocumentReference to the document, then call its collection() method. You'll need to use the id of each document for this. Since a QueryDocumentSnapshot subclasses DocumentSnapshot, you can use its id property for this:
let eventProducerRef = await db.collection('event_prods')
let allEventProducers = eventProducerRef.get().then(
producer => {
producer.forEach(snapshot => {
const docRef = eventProducerRef.doc(snapshot.id)
const subcollection = docRef.collection('eventGroups')
})
}
)
Related
I'm trying to create an empty new "Book" document in firestore with a randomly generated uid. At the same time I'd like to add data to a "Page" document in a subcollection called "Pages" within the book document. I haven't been able to make this work, do I need to explicitly reference a docId before writing to a subcollection?
export const addBookAndFirstPage = () => {
const pageRef = db.collection("books").doc().collection("pages").doc("page1");
return pageRef.set({ foo: "bar" });
};
I've solved this by creating the two references to each doc individually but also using add() instead of doc() as per the docs. Note that add() expects to take an object as an argument otherwise it throws the following exception:
FirebaseError: Function addDoc() called with invalid data. Data must
be an object, but it was: undefined
To create an empty document with a randomly generated uid we need to pass an empty object to the add method like below. We can then create the reference for the doc we intent to add to the subcollection and set data:
export const addBookAndFirstPage = async () => {
try {
let bookRef = await db.collection("books").add({}); // <--- Use add() with an empty object
let pageRef = await caseRef.collection("pages").doc("page1");
return await pageRef.set({ foo: "bar" });
} catch (error) {
console.log(error);
}
};
I am deleting a FRTDB node, I want to access deleted data from that node. the functions looks as follow:
exports.events = functions.database.ref('/events/{eventId}').onWrite(async (change, context) => {
const eventId = context.params.eventId
if (!change.after.exists() && change.before.exists()) {
//data removed
return Promise.all([admin.database().ref(`/events/${eventId}/dayofweek`).once('value')]).then(n => {
const pms = []
const days = n[0]
days.forEach(x => {
pms.push(admin.database().ref(`${change.before.val().active ? 'active' : 'inactive'}/${x.key}/${eventId}`).set(null))
})
return Promise.all(pms)
});
else {
return null;
}
})
The probem I am having is that
admin.database().ref(`/events/${eventId}/dayofweek
do not loop the data because it seems data is no longer there so the forEach is not working. How can I get access to this data and get to loop the deleted data?
Of course you won't be able to read data that was just deleted. The function runs after the delete is complete. If you want to get the data that was just deleted, you're supposed to use change.before as described in the documentation:
The Change object has a before property that lets you inspect what was
saved to Realtime Database before the event. The before property
returns a DataSnapshot where all methods (for example, val() and
exists()) refer to the previous value. You can read the new value
again by either using the original DataSnapshot or reading the after
property. This property on any Change is another DataSnapshot
representing the state of the data after the event happened.
The data that was deleted from the database is actually included in the call to your Cloud Function. You can get if from change.before.
exports.events = functions.database.ref('/events/{eventId}').onWrite(async (change, context) => {
const eventId = context.params.eventId
if (!change.after.exists() && change.before.exists()) {
//data removed
days = change.before.val().dayofweek;
...
})
I am trying to update a mongoose document, But its a deeply nested array of objects and I am having trouble updating it using the spread operator. I have an array of image-links and I wanna iterate through the relationships array in the database and add an image to each relation. The code shows my approach, but the syntax is wrong. I have added a db image which shows where I wanna add the image variable.
// Get Images
const imagesData = await axios.get(
"https://randomuser.me/api/?results=4&gender=male"
);
const images = [];
imagesData.data.results.forEach((result) => {
images.push(result.picture.large);
});
// Update Company
for (let i = 0; i <= 3; i++) {
const updateCompany = await Companies.findByIdAndUpdate(
req.params.id,
{ relationships: [
...relationships,
relationships[i]: {
...relationships[i],
image: images[i]}
] },
{ new: true }
).exec();
}
Also I am using a mongoose query inside a for loop. Is it the right way to do it.
mognoDB
You should fetch the document that you want. Then treat the fetched object as a javascript object and add or update whatever you want then use .save() function provided by mongoose.
let result = await Companies.findById(id);
result = result.map((company)=>{
update your object here
})
result.save()
The .save() function will take care of updating the object in the database
I am stuck in what I thought was a very simple use case: I have a list of client ids in an array. All I want to do is fetch all those clients and "watch" them (using the .onSnapshot).
To fetch the client objects, it is nice and simple, I simply go through the array and get each client by their id. The code looks something like this:
const accessibleClients = ['client1', 'client2', 'client3']
const clients = await Promise.all(
accessibleClients.map(async clientId => {
return db
.collection('clients')
.doc(clientId)
.get()
})
)
If I just needed the list of clients, it would be fine, but I need to perform the .onSnapshot on it to see changes of the clients I am displaying. Is this possible to do? How can I get around this issue?
I am working with AngularFire so it is a bit different. But i also had the problem that i need to listen to unrelated documents which can not be queried.
I solved this with an object which contains all the snapshot listeners. This allows you to unsubscribe from individual client snapshots or from all snapshot if you do not need it anymore.
const accessibleClients = ['client1', 'client2', 'client3'];
const clientSnapshotObject = {};
const clientDataArray = [];
accessibleClients.forEach(clientId => {
clientSnapshotArray[clientId] = {
db.collection('clients').doc(clientId).onSnapshot(doc => {
const client = clientDataArray.find(client => doc.id === client.clientId);
if (client) {
const index = clientDataArray.findIndex(client => doc.id === client.clientId);
clientDataArray.splice(index, 1 , doc.data())
} else {
clientDataArray.push(doc.data());
}
})
};
})
With the clientIds of the accessibleClients array, i create an object of DocumentSnapshots with the clientId as property key.
The snapshot callback function pushes the specific client data into the clientDataArray. If a snapshot changes the callback function replaces the old data with the new data.
I do not know your exact data model but i hope this code helps with your problem.
Here is a javascript function intending to perform an update on FireStore, which does not work.
I will be more that happy if anyone can see an issue in the code.
function makeUpdate(key,name) {
let theCollection = db.collection("InformationList"),
infoUnit = theCollection.doc(key).get().then(function(doc) {
if (doc.exists) {
console.log("infoUnit -name-:" + doc.get("name"));
console.log("infoUnit -telephone-:" + doc.get("telephone"));
let updateDico = {};
updateDico["name"] = name;
doc.update(updateDico);
} else {
console.log("embassyUpdate --> No such document!");
}
}).catch(err => {
console.log("Error getting documents (in makeUpdate)", err);
});
}
Apart from the fact that it does not perform the expected update, it prints three messages in the logs:
infoUnit -name-: some name
infoUnit -telephone-: some telephone number
Error getting documents (in makeUpdate)
From that I can see that a record is found in the database as expected. But at the same time an unknown error occurs.
There is no update() method on doc (which a DocumentSnapshot object). A DocumentSnapshot just contains the data read from get(). If you want to write data back into a document, you'll need to use a DocumentReference object, probably the same one you got when you called theCollection.doc(key).
There is no such method called update() which you can invoke on doc DataSnapshot object itself.
You'll have to use the set() method on the Document Reference which you get from doc.ref to update the reference.
This is how I've updated my data.
await db
.collection('collectionName')
.doc('documentId')
.update({
name: "Updated Name",
telephone: "0000000000"
});
You need to know document id and you can update your value like this.