Issues connecting data stream to users responses in Google Voice App - javascript

I am currently developing a voice agent to be used in a smart speaker where users will ask about some items that are being stored in a data stream. The ultimate goal is that users ask about items' names in the stream and google actions through voice will tell them the details about those items as presented in another column in the stream.
To do this, I linked a spreadsheet to Axios to stream the content of the spreadsheet as data to be read in a webhook in google actions. The link to the data stream is HERE.
Honestly, I am new to developing apps for google actions and new to javascript overall so I might be doing silly mistakes.
In the graphical interface for google actions, I am setting a type for the items I want the user to ask about.
Then, I set an intent to recognize the item as a data type and be able to send this to the webhook.
The cloud function in the webhook is as follows:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios');
const app = conversation({debug: true});
app.handle('getItem', async conv => {
const data = await getItem();
const itemParam = app.types.Item;
// conv.add("This test to see if we are accessing the webhook for ${itemParam}");
data.map(item => {
if (item.Name === itemParam)
agent.add('These are the datails for ${itemParam}. It is located in zone
${item.Zone}, at level ${item.Level}');
});
});
async function getItem() {
const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
console.log(res.data);
return res.data; // To use in your Action's response
}
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
What the webhook is doing is getting the stream with the getItem function and then mapping the data to find the Name in the stream to match the item parameter (ItemParam) as identified by the user.
However, one of the main problems I have is that when trying to access the item from the user, I am using app.types.Item, but this does not work as when testing I get an error saying: "error": "Cannot read property 'Item' of undefined". I think what is happening is that I am not using the correct way to call the Item in the conversation app.
Also, I am not sure exactly how the linking to the database will work. In other works, I am not sure if
data.map(item => {
if (item.Name === itemParam)
agent.add('These are the datails for ${itemParam}. It is located in zone
${item.Zone}, at level ${item.Level}');
will work.
I have tried multiple things to solve but I am really struggling so any help with this would be really appreciated. Also, I know that I rushed to explain things, so please let me know if you need me to explain better or clarify anything.
Thank you

There are three points I am seeing that won't work.
First, app.types.Item is not the way to get this parameter. You should instead use conv.intent.params['Item'].resolved to get the user's spoken name.
Second, you are trying to use agent.add to include text, but there is no agent in your environment. You should instead be using conv.add.
Third, the text you are sending is not properly escaped between backticks ``. It is the backtick that allows you to use template literals.
Altogether your code can be rewritten as:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios');
const app = conversation({debug: true});
app.handle('getItem', async conv => {
const data = await getItem();
const itemParam = conv.intent.params['Item'].resolved;
data.map(item => {
if (item.Name === itemParam)
conv.add(`These are the datails for ${itemParam}. It is located in zone
${item.Zone}, at level ${item.Level}`);
});
});
async function getItem() {
const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
console.log(res.data);
return res.data; // To use in your Action's response
}
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

Related

Importing User Data from filtered Array (VUE3 + Quasar + Firebase)

I am importing the data from the currently signed in user in order to manage the entire user profile page and all the associated actions.
On one hand I have the auth.currentUser and on the other I have the USERS collection in the db which stores all the additional data related to that particular user.
Now, my question concerns optimization. What would be the ideal way to get this user's data? Currently I am getting the entire users collection and filtering to get the one that matched the uid from the route params, yet I was told that loading the entire users collection and filtering the one I want to display was less than ideal, that I should rather create a function to get a specific user by a property such as name or id. This is what confuses me, is that not essentially what I am doing by filtering the users collection? How else would it be best to get that user's info? By creating this function in the Store and not in the component itself?
Currently it's looking like this:
UserPage.vue
const storeUsers = useUserStore();
const users = storeUsers.users;
const route = useRoute();
const id = route.params.id;
const userData = computed(() => {
return users.find((u) => u.uid == id);
});
Any way to optimize this would be appreciated.
*Adding a screenshot of the Firestore console (data model):
Your code is loading every document from the users collection into your application code, and then choosing there which single document you are actually interested in. Since you pay for every document read from the database, and you (and your users) pay for all bandwidth that is used, this is wasteful - especially as you start adding more users to the collection.
Instead you should use a query to read only the document(s) you are interested in from the database into your application code. Read the documentation for examples for all supported SDK versions.
finally solved it using a query as suggested. I am triggering the getUserInfo action whenever a user signs in and then assigning it to a pinia state called currentUserData:
AUTH STORE
async getUsers() {
onSnapshot(userCollectionRef, (querySnapshot) => {
let users = [];
querySnapshot.forEach((doc) => {
let user = {
did: doc.id,
...doc.data(),
};
this.users.push(user);
});
});
},
getUserInfo(userCredential) {
const q = query(
userCollectionRef,
where("uid", "==", userCredential.user.uid)
);
onSnapshot(q, (snapshot) => {
let currentUserData = [];
snapshot.docs.forEach((doc) => {
currentUserData.push({ ...doc.data(), id: doc.id });
});
this.currentUserData = currentUserData;
});
}

my API call is not working properly [React - ASP .Net Core]

I have had a problem for a long time that I do not understand very well why it happens, I tried everything else, however I always find it in one way or another, let me explain.
I am developing a split App, Front End with React JS and ASP .net in the BackEnd, so far so good.
I designed a page in which what I am looking for is, Before the components of my page are displayed, I want to make 2 calls to my back end to bring me 2 different resources in JSON format, both resources of Type GET and I want this to be displayed information in my components. the information I ask for is nothing special, just simple JSON text strings like username, identifier, numbers etc.
To make the call to my backend I use AXIOS, and in this case I use PROMISE JavaScript in React.
To execute it when mounting my component, I make use of React's UseEffect, in this way I execute the 2 calls.
I'm not using Redux, I'm just using SessionStorage and LocalStorage, the logic in my head is as follows:
1.-if the sessionStorage called Client does not exist, I will execute the function GetCliente
2.- The GetCliente function makes calls to the API with AXIOS and brings me the information of the client
3.- When I bring it, I convert the JSON into a Javascript object with JSON.stringify and in this way I create the Client sessionStorage.
4.- When the Client sessionStorage is created, it will be mounted on a UseState called client whose initial state is null.
5.- When the client useState is filled, it will be painted on the page, to paint it I use this notation client?.username, to access its values ​​​​and if it doesn't come, it won't mark me an error.
6.- When the sessionStorage called Client is created, if the user decides to "Refresh" the page, he will no longer have to make the API call because he is already registered on the page, so he will only have to mount the information of the sessionStorage in my UseState, this way I don't overload my server with requests.
Now here comes the tricky...
My logic works, I already have it implemented and it has worked, however the following errors start appearing.
1.- Sometimes, when I enter the page for the first time, of the 2 resources that I request, 1 does not arrive, I have 2 functions, getCliente() this brings me data from a client and getWarehouse() this brings me data from a warehouse.
sometimes the information from getCustomer does not arrive but the information from getWarehouse does, and on other occasions the information from getWarehouse does not arrive but the information from getCustomer does.
I have a button called close session that cleans the sessionStorage, when I try to enter the page again it does not bring me any of the 2 resources!
I went to the Network tab of my browser, and sometimes I see that my 2 resources are executed 2 times, according to what I know is by UseEffect, that it executes my function 2 times, however in the 2 occasions the request of my 2 resources are in status 304
sometimes when I go to the network tab, I see that one of my resources is in status 304, and then that same resource is executed again by the UseEffect and the status appears in 200, a sign that it was achieved but for some reason , it doesn't load into my SessionStorage! It appears to me that the client SessionStorage was created but it is empty!
I don't know what to do anymore, I have greatly simplified this logic at this point, however sometimes it works very well and other times it doesn't!
Now yes, I attach all the code, I don't really know what I'm doing wrong, even my backend doesn't do other things like verify token or something like that, it just asks for the resource and sends it but I don't understand why it keeps happening...
First Server code this is my endpoint that brings data from my store...
[HttpGet("almacen/{dbhandle:int}/{idcaja:int}")]
public ActionResult<string> getAlmacen(int dbhandle, int idcaja) {
string [] data = ConexionDB.Instance.Obtener_almacen_caja(dbhandle, idcaja);
var dataconvert = JsonConvert.SerializeObject(data);
return Ok(dataconvert);
}
this is my endpoint that brings my user data
[HttpGet("cliente/{dbhandle:int}")]
public ActionResult<String> getcliente(int dbhandle) {
string [] data = ConexionDB.Instance.Obtener_cliente(dbhandle);
var dataconvert = JsonConvert.SerializeObject(data);
return Ok(dataconvert);
}
both endpoints work, both with PostMan I have tested it
Now code in React...
const VentasMostrador = () => {
//varibles de estado useState
const [cliente, setcliente] = useState(null);
const [almacen, setalmacen] = useState(null);
const [cajero, setcajero] = useState(null);
const [productos, setproductos] = useState([]);
const [cambio, setcambio] = useState(false);
const [total, setTotal] = useState(0);
const [show, setShow] = useState(false);
const [productoSeleccionado, setProductoSeleccionado] = useState(null);
const [seriesylotes, setseriesylotes] = useState(null);
if(!sessionStorage.getItem("ID_CAJA")){
window.location = "/PaginaPrincipal";
}
const getCliente = async () => {
let user = JSON.parse(localStorage.getItem("datauser"));
const promise = await axios.get("https://localhost:5001/api/ventasmostrador/cliente/"+user.DbHandle);
if(promise){
let data = promise.data;
let infodata = { id: data[0], nombre: data[1], codigo: data[2] };
sessionStorage.setItem("GET_CLIENTE", JSON.stringify(infodata));
setcliente(JSON.parse(sessionStorage.getItem("GET_CLIENTE")));
} else {
console.log("no se pudo cargar los datos de almacen...");
}
};
const getAlmacen = async () => {
let user = JSON.parse(localStorage.getItem("datauser"));
let caja = JSON.parse(sessionStorage.getItem("ID_CAJA"));
const promise = await axios.get("https://localhost:5001/api/ventasmostrador/almacen/"+user.DbHandle+"/"+caja);
if(promise){
let data = promise.data;
let infodata = {
id: data[0],
caja: data[1],
idalmacen: data[2],
nombrealmacen: data[3],
};
sessionStorage.setItem("GET_ALMACEN", JSON.stringify(infodata));
setalmacen(JSON.parse(sessionStorage.getItem("GET_ALMACEN")));
} else {
console.log("no se pudo cargar los datos de almacen...");
}
};
now to execute these 2 functions I make use of UseEffect.
useEffect(() => {
let datauser = JSON.parse(localStorage.getItem("datauser"));
setcajero(datauser.Nombrecajero);
}, [])
useEffect(() => {
if(!sessionStorage.getItem("GET_CLIENTE")){
getCliente();
} else {
setcliente(JSON.parse(sessionStorage.getItem("GET_CLIENTE")));
}
console.log("cuanto se ejecuta x1...");
}, []);
useEffect(() => {
if(!sessionStorage.getItem("GET_ALMACEN")){
getAlmacen();
console.log("cuanto se ejecuta x2...");
} else {
setalmacen(JSON.parse(sessionStorage.getItem("GET_ALMACEN")));
}
}, [])
Evidence of all my explanation...
This image is when I entered the application for the first time, here it executed perfectly and the data came out.
enter image description here
here the information is painted in my component, all good and in the tab where sessionStorage is located both objects are created and filled.
enter image description here
Here comes the problem, when I press the button, logout, and I leave this page, and try to enter again so that everything can be reloaded, it stops working or 1 resource, or another resource or BOTH :(
enter image description here
If I check the network tab, they appear to me that they arrived!
enter image description here
So I don't know what to do, I know the explanation is too long and tedious but this frustrates me, I don't know if the controller, useEffect, my javascript function or the promise is wrong.
If anyone reads this please help :(

Cannot map variable from data stream to users identified response while developing voice app

I am currently developing a voice app with Google Actions where users are able to ask for information about items in a list that is provided through a file stream with Axios as shown in the following LINK. The data looks like this:
[
{
"Name": "Beam",
"Level": "2",
"Zone": "A",
"Location": "Beam is located on Level 2 in zone A",
"Responsible": "Contractor"
},
{
"Name": "Column",
"Level": "3",
"Zone": "A",
"Location": "Column is located on Level 3 in zone A",
"Responsible": "Kiewit"
},
{
"Name": "Window",
"Level": "2",
"Zone": "B",
"Location": "Window is located on Level 2 in zone B",
"Responsible": "Tech"
}
]
Here, it shows three items being a BEam, a Column, and a Window so the objective is that users ask about one of the items and the voice app will provide the other information such as Level, ZOne, Location, or Responsible to the user.
To complete this, I am using the web interface of Google Actions and using inline cloud functions as webhooks in Google Actions that looks like this:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios');
const app = conversation({debug: true});
app.handle('getItem', async conv => {
const data = await getItem();
const itemParam = conv.intent.params.Item.resolved;
// console.log(itemParam);
// conv.add(`This test to see if we are accessing the webhook for ${itemParam}`);
data.map(item => {
if (item.Name === itemParam);
conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
// conv.add(`This test to see if we are accessing the webhook for ${item.Name}`);
});
});
async function getItem() {
const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
console.log(res.data);
return res.data; // To use in your Action's response
}
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
When I check the console logs, I can see that I am retrieving the data in a single event as provided in the LINK. Also, the recognition of the item name is working in the app by defining a type within the app to be recognized based on type categories. And this information is being stored in ItemParam.
However, the main issue I have right now is to link both things together. I was trying to use a map function to match the itemParam and the Item.Name from the data stream. However, this is not working at al. The function I was trying to do is:
data.map(item => {
if (item.Name === itemParam);
conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
What I am trying to do here is when the function detects that the user ItemParam is matched to the Item in the stream, use the information from that stream item and add a phrase to the conversation that includes the ItemParam, and the other information about that same item.
Besides, the way this function is right now, also shoots this error:
cf-GPfYHj4HKDWGvHKWArq34w-name
Error: Error adding simple response: **Two simple responses already defined**
at addSimple (/workspace/node_modules/#assistant/conversation/dist/conversation/prompt/prompt.js:34:15)
at Prompt.add (/workspace/node_modules/#assistant/conversation/dist/conversation/prompt/prompt.js:108:17)
at ConversationV3.add (/workspace/node_modules/#assistant/conversation/dist/conversation/conv.js:102:21)
at data.map.item (/workspace/index.js:16:13)
at Array.map (<anonymous>) at app.handle (/workspace/index.js:14:8) at process._tickCallback (internal/process/next_tick.js:68:7)
I am honestly not that familiar with Javascript and I might be doing silly mistakes but I really cannot figure out this.
Any help will be much appreciated. Thank you
The error you are seeing is:
Error: Error adding simple response: Two simple responses already defined
Your action's response can only include two simple responses. Each response is rendered as a separate text bubble on a phone, for instance.
So it seems like the item.Name === itemParam is true multiple times and you end up creating too many responses.
Why does this happen? It comes from how your conditional is written:
data.map(item => {
if (item.Name === itemParam);
conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
});
You have correctly identified that the ; semicolon character denotes the end of a statement. However, this does not apply to if statements. Because the way it's written, you have this conditional and then conclude it before you actually run conv.add. This means that conv.add escapes your check and runs for every item. If you were to log the conv response, you'd see a bunch of text.
To fix it, keep in mind that a conditional needs to wrap the surrounding code. This is done with curly braces { & }.
data.map(item => {
if (item.Name === itemParam) {
conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
}
});
You can even see this in the map method, where the mapping logic surrounds your if-statement with curly braces. This shows that one is contained entirely within the other.
Thanks, Nick, I fixed my function based on your feedback and now I understand a little better about the map function. Another issue that I figured out along the way was that upper and lower case does matter to match the map function so I also had to modify the type to lowercase and add .toLowerCase() methods to variables.
Now my code is working with two variables Item and Item_ID so if the user asks about a generic item, it can get detailed by adding the ID of the item to the query question.
Now my code looks like this:
// From here, there are all the required libraries to be loaded
const { conversation } = require('#assistant/conversation'); // This the app coversation
const functions = require('firebase-functions'); //These are the firebase functions
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios'); // This is axios to retrieve the data stream
// To here, there all the required libraries to be loaded
const app = conversation({debug: true}); // This instantiate the conversation
/* This function retrieve the data from the file stream */
async function getItem() {
const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
return res.data; // To use in your Action's response
}
/* This is the fuction to match user's responses and data stream*/
app.handle('getItem', async conv => { //getItem is the weekhook name used in Google Actions, conv is the conversation
const data = await getItem(); // Here the data stream is retrieved and send to the data variable
// console.log(data);
const itemParam = conv.intent.params.Item.resolved; // This is the user's response, in other words, what item the user's want to know from the data.
const itemIDParam = conv.intent.params.Item_ID.resolved.replace(/\s/g, ''); //This is the user's response for item ID
const itemFromUser = itemParam + " " + itemIDParam;
console.log(itemParam);
console.log(itemIDParam);
console.log(itemFromUser);
// conv.add(`This test to see if we are accessing the webhook for ${itemParam}`); // This is to know if I was getting the correct item from the user. Currently this is working
// console.log(data);
data.map(item => { //Then, I am trying to map the data stream to recognize the data headers and identify items
// console.log(data);
// console.log(item);
if (item.Name.toLowerCase() === itemFromUser.toLowerCase()){
console.log(item);
conv.add(`These are the details for ${itemFromUser}. It is located in zone ${item.Zone}, at level ${item.Level}.`);
// console.log(conv);
// console.log(data);
}
else {
conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
}
});
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
Now I can handle most of the questions except when something is not in the data stream which makes the app to show me this error:
"error": "Error adding simple response: Two simple responses already defined"
This is the same error as I was getting before and I am not sure how to fix it yet. I tried to implement an else statement for that condition as follows:
else {
conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
}
But I am still getting same error.
I am still working on this.

Is it possible if I can get the last key (latest message) added from the realtime database?

I would like to get the last key (the latest message) from my realtime database but not sure how this can be achieved.
I see from this link i need to get Last child of my firebase databse that I can use orderByKey().limitToLast(1) to get this but it looks like I need to specify the complete ref in order to achieve this. Is that correct? Or is it possible if I can orderByKey().limitToLast(1) on the val()? Or is there another way I can achieve this?
Here is my messages structure in the database:
I have a timestamp child under each key as shown above which I thought I could query in order to extract the latest key but I really don't know how to do this. Can someone please help? Below is my code so far:
database().ref(`messages/`).once(`value`, snapshot => {
if(snapshot.exists()) {
snapshot.forEach(function (childSnapshot) {
if(childSnapshot.key.includes(auth().currentUser.uid)) {
console.log("show me the key: "+childSnapshot.key)
//not working
console.log("show last message: "+ JSON.stringify(childSnapshot.val().orderbyKey().limitToLast(1)))
}
})
}
})
console.log(JSON.stringify(messages)) => [{"-MfqYBzbusp1Cljgxpan":{"unreadMessage":true,"user":{"name":"Mike","avatar":"xxxxxx","_id":"tFhmw5oQoPhk8nF2sx5rE5BFqw93"},"timestamp":1627634061437,"senderId":"tFhmw5oQoPhk8nF2sx5rE5BFqw93","notification":{"body":"Hey","title":"Project","imageUrl":"./assets/xxxxx.png"},"text":"Hey"}}]
console.log(JSON.stringify(unreadMsgs)) => []
Firebase Realtime Database queries work on a flat list of nodes. So if you have a specific path /messages/nodeid already, you can find the latest message under that, but you can't find the latest message across all of /messages.
Reading all messages from all chatrooms, just to find the latest message for each chatroom this user is in is really wasteful though. As you add more users to the app, you're driving up the bandwidth cost for them, and for yourself too.
I recommend keeping a separate node where you track the chat rooms for each user, as explained in my answer on Best way to manage Chat channels in Firebase. With such a node you can then easily determine just the chat rooms for the current user, and then load the latest message for each of them with something like:
database().ref(`user_chatrooms/${auth().currentUser.uid}`).once(`value`, indexSnapshot => {
indexSnapshot.forEach((indexSnapshotChild) => {
let chatroomId = indexSnapshotChild.key;
let query = database().ref(`messages/${chatroomId}`).orderByChild("timestamp").limitToLast(1)
query.once(`value`, (msgSnapshot) => {
console.log(`Last message in ${chatroomId} was ${msgSnapshot.val().text}`);
})
}
})
The orderByKey and limitToLast methods exists on a DatabaseReference and not on the value you fetch from the snapshot fetched earlier. It seems the parent key for all messages is of format userId1userId2. If you know this combination then you run your query this way.
const uidsKey = "uid1" + "uid2"
const query = database().ref(`messages/${uidsKey}`).orderByChild("timestamp").limitToLast(1)
query.once("value").then((snapshot) => {
console.log(snapshot.val())
})
But it seems you are trying to get UIDs of others users who have chats with user1 and trying to real all nodes first. I won't recommend doing that as that might have issues with security rules and so on. Instead if you keep list of those UIDs somewhere else, it'll be better. But if you want to keep what you have right now, try this:
const userUID = auth().currentUser.uid
database().ref("messages/").once("value").then(async (msgSnapshot) => {
const keys = Object.keys(msgSnapshot.val() || {})
const userChatKeys = keys.filter(k => k.includes(userUID))
//const otherUserIDs = userChatKeys.map(k => k.replace(userUID, ""))
//userChatKeys will be chat IDs where current user is included
//now follow the same steps mentioned in first code snippet
const queries = userChatKeys.map(chat => database().ref(`messages/${chat}`).orderByChild("timestamp").limitToLast(1).once("value"))
const lastMessagesSnap = await Promise.all(queries)
const messages = lastMessagesSnap.map(m => Object.values(m.val())[0]))
console.log(`messages: ${messages}`)
const unreadMsgs = messages.filter((msg) => msg.unreadMessage === true)
console.log(unreadMsgs.length)
})
This will logs last message from each of user's chat.

Get Every Document from inside a Users Collection Firebase

I have written a Firebase cloud function in which I want to get every users internal collection called 'numbers' and read each document out of that collection to do some comparisons.
Any idea how to do this?
I am pretty new to firebase and for some reason the database navigation commands are just not sticking with me very well.
I have tried a handful of commands with no success
const snapshot = functions.database.collection('users').collection('numbers').get()
let sfRef = db.collection('users');
sfRef.getCollections().then(collections => {
collections.forEach(collection => {
console.log('Found subcollection with id:', collection.id);
});
});
Here is a loose cloud code infastructure
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
export const prize1 = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
const users = functions.database.ref('/users/numbers')
console.log("")
return null;
});
I feel like I have a good idea of how to do it, but the syntax is holding me back.
The collection of users. Go through each document in here, i.e. each user.
In each user go to the collection called numbers.
In the collection called numbers go through each document and find the numbers field to do logic/comparisons with.
Hopefully this can help you understand the way my database is ordered.
You could try it like this:
let usersRef = db.collection('users');
let allUsers = usersRef.get();
.then(userSnapshot => {
userSnapshot.forEach(userDoc => {
userDoc.ref.collection('numbers').get().then(numSnapshot => {
numSnapshot.forEach(numDoc => {
console.log(numDoc.data().numbers);
// here you got your numbers document with the numbers field
});
});
});
})
.catch((error) => {
console.log("Error getting document: ", error);
});
For more information you can look here and here.
You can't use functions for accessing the database. What you've defined as functions is for building triggers that respond to events. If you want to get data from Cloud Firestore, you should be using the Firebase Admin SDK via your admin instead. It might also help if you look through the official samples.
I will also point out that your code samples appear to be split between accessing Cloud Firestore and Realtime Database, which are different database products. Your screenshot shows Firestore, so ignore any APIs for Realtime Database.

Categories