Given the following data struct in firebase, I wish to retrieve the field in just standard JS. I have tried many methods of getting it, but for some reason, I cannot. I have tried .get(), forEach(), I have tried getting a snapshop, but it won't work.
At the start of my JS file I do:
const auth = firebase.auth();
const db = firebase.firestore();
let totalGroups;
db.collection('totalGroups').doc('totalGroups').get().then(function(querySnapshot) {
querySnapshot.docs.forEach(function(doc) {
if (doc.data().totalGroups != null) {
totalGroups = doc.data().totalGroups console.log("here is total groups" + totalGroups)
//Total Groups is undefined out here but defined in fuction
}
})
})
and normally I am able to get .get() just fine. I am looking for the most simple method of getting this value. thanks.
First, you are using get() on a DocumentReference which returns a DocumentSnapshot containing data of that single document only and has no docs property on it. Try refactoring the code as shown below:
db.collection('totalGroups').doc('totalGroups').get().then(function(snapshot) {
const docData = snapshot.data();
console.log(docData)
})
Also do note that if you were using get() on a CollectionReference, then it would have returned a QuerySnapshot where the existing code works fine.
Related
I posted a question earlier about how to query for a specific value inside an array. I was told that there was a similar question already asked. I have looked at the solution for that question however i am getting an error. This is my code currently to check to see if the field mal_id inside the favourites array contains an id passed by me.
const docRef = collection(db, 'users')
const q = query(docRef, where('favourites', 'array-contains', {mal_id: id}))
I then attached an onSnapshot method to see if the data exists which is like this
onSnapshot(q, (snapshot) => {
if(snapshot.data()){
console.log(true)
}
else{
console.log(false)
}
})
But i get an error saying snapshot.data is not a function. idk if you are not supposed to use an onSnapshot method on this kind of query or my code is wrong. I have attached a picture of my database structure. Thanks.
*Edit
So, i have changed my data structure. Now i am creating a new field called animeID and then storing the id into it. I then do the array contains onto that but the snapshot still gives me the same error. Here is the updated code along with a new picture of my database structure.
const docRef = collection(db, 'users')
const q = query(docRef, where('animeID', 'array-contains', `mal_id: ${id}`))
onSnapshot(q, (snapshot) => {
if(snapshot.data()){
console.log(true)
}
else{
console.log(false)
}
})
Updated firestore structure
As Doug commented, Firestore's array-contains operator checks for equivalence between the value you supply and an entire array item. It can't find a subset of an item.
The common workaround is to add an additional field to your document with just the mal_id values you want query on. So something like:
Favourites_mal_ids: [21]
And then you can perform an array-contains on that field.
This is definitely a newbie question, and in part answered in the Firebase documentation, but for the life of me it's not working when implementing it in my own code - so I'm hoping the community can help me understand what I am doing wrong, and how to fix it.
When getting documents from Firestore, I can't access the actual values within, due to its structure, so when setting e.g. "var name = doc.name" it just gives me undefined. For getting MULTIPLE documents, I've already found apiece of code that works:
// Getting the document
docRef.collection(collectionRef).get()
.then((snapshots) => cleanData(snapshots))
.then((items) => items.map((item) => sampleFunction(item)));
// Firebase Utility cleaning documents (array)
function cleanData(snapshots) {
let data = [];
snapshots.forEach(function(doc) {
data.push({
id: doc.id,
...doc.data()
});
});
return data;
}
But when using this piece of code with e.g. collection("x").doc("id"), then it throws the error:
"Uncaught (in promise) TypeError: snapshots.forEach is not a function"
So I went ahead to modify the function as follows:
// Firebase Utility cleaning document (single)
function cleanDoc(snap) {
let data = [];
data.push({
id: doc.id,
...doc.data()
});
return data;
}
But that gives me "undefined" when attempting to access the values in my function again...
The documentation (in the city example) says to define a class. When I did that, I was able to get values from one document, but it gave me undefined the second time I called the same function on one page.
For context, I'm trying to display a User Profile, which displays people they work with on a project, which means I call these profiles as well, the data structure just callsa reference to the "worked with" profiles, and I get their ID's just fine, but when attempting to render an HTML item for each, the values within their profiles are undefined....Its confusing the hell out of me anyways.
If your function is an async function:
collectionSnap = await docRef.collection(collectionRef).get();
val items=[]
await Promise.all(querySnap.docs.map(async (doc) => {
// Do your your work and populate items
}));
// Do your work with items
You can try this approach to processing your documents.
Trying to remove an item from the firebase array using arrayRemove but I'm getting the following error:
ReferenceError: Can't find variable: FieldValue
const removeItemHandler = () => {
//this logs the array item like is should, dont think this value is the issue
console.log(props.item)
console.log(props.currentNote)
//removes note from the notes array
db.collection('users').doc(userEmail)
.collection('books').doc(props.currentBook)
.collection('specific').doc(props.currentNote).update({
notes: FieldValue.arrayRemove(props.item)
})
showRemoveButton(false)
}
I was following the example linked below, really not sure why my, very similar situation is giving me this error. Thank you!
https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
also, keep in mind that props.item is referencing the array items name, I checked the type and the value with the console.log's and it is correct. Confident that is not part of the issue.
You are accessing FieldValue which is undefined. You cannot access it directly.
You can access it via firebase.firestore.FieldValue or if you imported firestore directly then firestore.FieldValue. So change your code like this :
const removeItemHandler = () => {
//this logs the array item like is should, dont think this value is the issue
console.log(props.item)
console.log(props.currentNote)
//removes note from the notes array
db.collection('users').doc(userEmail)
.collection('books').doc(props.currentBook)
.collection('specific').doc(props.currentNote).update({
notes: firebase.firestore.FieldValue.arrayRemove(props.item)
notes: firestore.FieldValue.arrayRemove(props.item) // or if you are imported firestore
})
showRemoveButton(false)
}
I am using sequelize to run a raw MSSQL update query. The documentation for raw update queries states that the message for number of rows updated will be contained in the metadata. In the following function both results and metadata are undefined on update statements. It works perfectly fine if I use a normal select statement.
Documentation
The section in reference is the very first example.
Could someone help me understand what I am doing incorrectly?
var query = 'UPDATE contacts SET aolid = 1 WHERE contactid = 804748'
connection.query(query).spread(([results, metadata]) => {
console.log(metadata) // will log undefined
console.log(results) // will log undefined
})
Either use
.then(([results, metadata]) =>
or
.spread((results, metadata) =>
but .spread(([results, metadata]) => will not work. See spread().
I'm trying to get firebase data from a node which uid must start with a passed string.
I tried a code but I always get the same data. The database data is as following:
And I'm using the following code:
var ref = firebase.database().ref("restaurantes/history");
ref.orderByKey().startAt(userUID).once("child_added", function(snapshot) {
snapshot.forEach(child => {
if(child.key == "orders")
{
console.log(child.val());
_.each(child.val(), (value, key) => {
arrtmp.push(value)
})
}
})
If user is "FKQLlqa" I should get the history data shown in the picture. If I user is "abc" I shouldn't get any data. But I always get the data shown in the picture. Should I use another way of querying? Or I should use a key field inside orders and payments data?
Regards!
Try the following:
var ref = firebase.database().ref("restaurantes/history");
ref.child(userUID).once("value", function(snapshot) {
if (snapshot.exists()) {
console.log(snapshot.val());
}
else {
console.log("different user");
});
This will check if the snapshot that contains the userId (added as a parameter in the child() method), already exists in the database then you will be able to retrieve the data under the userId.
For reference:
https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#exists
Peter's answer is the correct solution. I'm merely adding this for completeness.
When you call orderBy... on a Firebase reference, the database orders all child nodes on the key/value/child that you specify.
If you then subsequently call startAt(...) on the query, it finds the (first) node that starts with that value and starts returning all results from there. So if you start at FKQLlqa, it will start returning keys at FKQLlqa and then return all keys after it.
If you want to return the child node(s) with a specific key/value/child, you'd use equalTo(...). So:
ref.orderByKey().equalTo(userUID).once("child_added", function(snapshot) {
...
But as Peter said already, this is just a more expensive way to look up a child with a known key. I highly recommend using his better approach: ref.child(userUID).once("value".