realtime firebase database (0, _database.where) is not a function - javascript

ERROR
ERROR TypeError: (0, _database.where) is not a function. (In '(0, _database.where)('email', '==', email)', '(0, _database.where)' is undefined)
In here I am generating a uniqe perant in the database using uid and update some values in it, I am trying to do some filitration based on the email to know if users exist then update the values if not then generate a new user
import { ref, get, set, query, where} from 'firebase/database';
useEffect(() => {
const writeToDatabase = () => {
if (location && location.coords && UserDataFromGoogleAuth) {
const usersRef = ref(database, 'users');
const email = UserDataFromGoogleAuth.email;
if (email) {
const query = query(usersRef, where('email', '==', email));
get(query).then((snapshot) => {
const uuid = snapshot.exists() ? Object.keys(snapshot.val())[0] : uid();
const userRef = ref(database, `/users/${uuid}`);
const userData = {
id: uuid,
name: UserDataFromGoogleAuth.displayName,
email: email,
includedKids: 0,
isSubscribed: false,
long: location.coords.longitude,
lat: location.coords.latitude,
online: props.online,
profilePicture: UserDataFromGoogleAuth.photoURL,
};
set(userRef, userData);
}).catch(error => {
console.log(error);
});
}
}
};
writeToDatabase();
}, [UserDataFromGoogleAuth, location, props.online]);
database structure:
Database> users> {uid foreach user}> {email}

The where method is part of the Cloud Firestore API (firebase/firestore).
There is no direct equivalent in the Realtime Database API (firebase/database) that allows using a similar shorthand.
Instead, you invoke one of the many QueryConstraint returning methods:
endAt(), endBefore(), startAt(), startAfter(), limitToFirst(), limitToLast(), orderByChild(), orderByChild(), orderByKey(), orderByPriority(), orderByValue() or equalTo(). Take a look at QueryConstraint for links to the API reference for these methods and read over the documentation for Realtime Database: Sorting and filtering data.
The equivalent of
// firestore
const query = query(usersColRef, where('email', '==', email));
is
// database
const query = query(usersRef, orderByChild('email'), equalTo(email));

Related

get updated value with firestore

I'm trying to get a doc in a collection and if it doesn't exist I create a new one, I would like to know if there is any way to get userData even if it doesn't exist (so to assign it the new one I have created) or I need to take it with
firebase
.firestore()
.collection("users")
.doc(ID);
again
const userRef = firebase
.firestore()
.collection("users")
.doc(ID);
const user = await userRef.get();
if (!user.exists) {
userRef.set(userSchema);
}
const userData = user.data();
I'm not sure where the user data is coming from but let's have a test user as follows:
const userData = {
name: "TestUser",
uid: "1234",
verified: true
}
Then here goes the function you need:
async function addUserToDatabase(userData) {
//Document Reference
const userDocRef = admin.firestore().collection("users").doc(userData.uid)
//Checking if document exists
if ((await userDocRef.get()).exists) {
return "User document already exists!"
}
//Document does not exists so create one
await userDocRef.set(userData)
return
}

Unable to retrieve data from Multiple collection firebase

Hope you're in good health.
I have a problem.
export function fetchListing() {
return function (dispatch) {
dispatch(fetchListingRequest());
//Getting Listing where status is in_review
firebase
.firestore()
.collection("listings")
.where("status", "==", "in_review")
.onSnapshot(
snapshot => {
const data = [];
snapshot.docs.forEach(doc => {
const temp = {};
// Getting address of business
firebase
.firestore()
.collection("users")
.doc(doc.data().business_id)
.get()
.then(users => {
temp["address"] = users.data().address;
})
.catch(error => {
dispatch(fetchListingFailed(error));
});
temp["title"] = doc.data().title;
temp["description"] = doc.data().description;
temp["listing_file"] = doc.data().listing_file;
data.push([doc.id, temp]);
});
dispatch(fetchListingSucess(data));
},
error => {
dispatch(fetchListingFailed(error));
}
);
};
}
I am Unable to get address in state but when I log it It displayed in console. I am able to access address when I am retrieving it from firebase and also in reducer I am also getting address.
reasons can be :
The hierarchy of your firestore collection
or you have to know that in js you can't affect the data to a variable that is in the main prog just when it is in a one level functions
for exemple here you can do this
locale = this ;
than you can use all the variables in two other levels

How to parameterize Firestore sub collection names in Cloud Function?

My Firestore sub collection names are of the format 'subcollection_name_yyyymmdd'. Whenever new documents are added, they are identified through the 'yyyymmdd' part of the subcollection name. I need to take Firestore exports for these subcollections incrementally on the 'yyyymmdd' values. Below is my cloud function taking full firestore export at the moment. Is there a way I can parameterize the 'collectionIds:' to take the subcollection names by passing the yyyymmdd part as a variable/parameter?
eg: something like collectionIds: ['subcollection_name_{$date}']?
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://BUCKET_NAME'
exports.scheduledFirestoreBackup = (event, context) => {
const databaseName = client.databasePath(
// process.env.GCLOUD_PROJECT,
"PROJECT_ID",
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: ['subcollection_name'],
})
.then(responses => {
const response = responses[0];
console.log(`Operation Name: ${response['name']}`);
return response;
})
.catch(err => {
console.error(err);
});
};

Get data from fire base to node.js file

I want to get data from my database on fire base and want to save that data to amount amount: snapshot, I did apply this const snapshot = firestore.collection('payment').doc(context.params.amount).get(); does that works in the same way? but I am getting an error that context is undefined.
I actually want to get data from database.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const firestore= admin.firestore();
const stripe = require('stripe')('');
const snapshot = firestore.collection('payment').doc(context.params.amount).get();
const customer = stripe.customers.create({
email: 'customer#example1.com',
});
stripe.customers
.create({
email: 'foo-customer#example.com',
})
.then((customer) => {
return stripe.customers.createSource(customer.id, {
source: 'tok_visa',
});
})
.then((source) => {
return stripe.charges.create({
amount: snapshot,
currency: 'usd',
customer: source.customer,
});
})
.then((charge) => {
// New charge created on a new customer
})
.catch((err) => {
// Deal with an error
});
you are trying to get amount through accessing params through context,
depends on your error, this means context is undefined which means you are trying to get params of undefined. you need to explain what is context means here, is it a global variable? is this code inside a cloud function? if yes you need to move this declaration const snapshot = firestore.collection('payment').doc(context.params.amount).get();
inside your cloud function ,
this is an example of firebase cloud function

Query firestore database for document id

I want to query a firestore database for document id. Currently I have the following code:
db.collection('books').where('id', '==', 'fK3ddutEpD2qQqRMXNW5').get()
I don't get a result. But when I query for a different field it works:
db.collection('books').where('genre', '==', 'biography').get()
How is the name of the document id called?
I am a bit late, but there is actually a way to do this
db.collection('books').where(firebase.firestore.FieldPath.documentId(), '==', 'fK3ddutEpD2qQqRMXNW5').get()
This might be useful when you're dealing with firebase security rules and only want to query for the records you're allowed to access.
Try this:
db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get()
(The first query is looking for an explicit user-set field called 'id', which probably isn't what you want.)
You can use the __name__ key word to use your document ID in a query.
Instead of this db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get() you can write
db.collection('books').where('__name__', '==' ,'fK3ddutEpD2qQqRMXNW5').get().
In this case you should get an array of length 1 back.
The firebase docs mention this feature in the rules documentation. https://firebase.google.com/docs/reference/rules/rules.firestore.Resource
June, 2021
The new v9 modular sdk is tree-shakeable and results in smaller compiled apps. It is recommended for all new Firestore apps.
import { doc, getDoc } from "firebase/firestore";
const snap = await getDoc(doc(db, 'books', 'fK3ddutEpD2qQqRMXNW5'))
if (snap.exists()) {
console.log(snap.data())
}
else {
console.log("No such document")
}
This is based on the example from the firestore docs
import { doc, getDoc } from "firebase/firestore";
const docRef = doc(db, "cities", "SF");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
}
else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
You could make this into a helper function
async function getDocument (coll, id) {
const snap = await getDoc(doc(db, coll, id))
if (snap.exists())
return snap.data()
else
return Promise.reject(Error(`No such document: ${coll}.${id}`))
}
getDocument("books", "fK3ddutEpD2qQqRMXNW5")
You can get a document by its id following this pattern:
firebase
.firestore()
.collection("Your collection")
.doc("documentId")
.get()
.then((docRef) => { console.log(docRef.data()) })
.catch((error) => { })
While everyone is telling to use .get(), which is totally reasonable but it's not always the case.
Maybe you want to filter data based on id (using a where query for example).
This is how you do it in Firebase v9 modular SDK:
import {collection, documentId} from 'firebase/firestore'
const booksRef = collection('books')
const q = query(booksRef, where(documentId(), '==', 'fK3ddutEpD2qQqRMXNW5'))
Currently only working way for Cloud Functions if you really need to use this way:
// Import firebase-admin
import * as admin from "firebase-admin";
// Use FieldPath.documentId()
admin.firestore.FieldPath.documentId()
const targetUser = await db.collection("users").where(admin.firestore.FieldPath.documentId() "==", "givenId").get();
Simpler way of this is directly using ID value thru path as there is only one document with given document ID:
const targetUser = await db.doc("users/"+ "givenId").get();
However, you may really need to use it if you are matching given IDs array to the Firebase collection like this:
const admin = require("firebase-admin");
const arr = ["id1", "id2"];
const refArr = arr.map(id => admin.firestore().collection("media").doc(id));
const m = await admin
.firestore()
.collection("media")
.where(admin.firestore.FieldPath.documentId(), "in", refArr)
.get();
This last example is from this discussion
If you are looking for more dynamic queries with a helper function, you can simply try this.
import { db} from '#lib/firebase';
import {query, collection, getDocs ,documentId } from "firebase/firestore";
const getResult = async (_value) => {
const _docId = documentId()
const _query = [{
field: _docID,
operator: '==',
value: _value
}]
// calling function
const result = await getDocumentsByQuery("collectionName", qColl)
console.log("job result: ", result)
}
// can accept multiple query args
const getDocumentsByQuery = async (collectionName, queries) => {
const queryArgs = [];
queries.forEach(q => {
queryArgs.push(
where(q.field, q.operator, q.value)
);
});
const _query = query(collection(db, collectionName), ...queryArgs);
const querySn = await getDocs(_query);
const documents = [];
querySn.forEach(doc => {
documents.push({ id: doc.id, ...doc.data() });
});
return documents[0];
};
From Firestore docs for Get a document.
var docRef = db.collection("cities").doc("SF");
docRef.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
This is the first link that came up when I was looking to solve it in the Golang SDK, so I'll add my solution in case anyone else is looking for it:
package main
import (
"context"
"fmt"
"log"
"cloud.google.com/go/firestore"
firebase "firebase.google.com/go/v4"
"google.golang.org/api/option"
)
type (
Car struct {
ID string
Name string `firestore:"name"`
Make string `firestore:"make"`
Price float64 `firestore:"make"`
}
)
func main() {
ctx := context.Background()
// Use a service account
options := option.WithCredentialsFile("PATH/TO/SERVICE/FILE.json")
// Set project id
conf := &firebase.Config{ProjectID: "PROJECT_NAME"}
// Initialize app
app, err := firebase.NewApp(ctx, conf, options)
if err != nil {
log.Fatal(err)
}
// Get firestore client
client, err := app.Firestore(ctx)
if err != nil {
log.Fatal(err)
}
defer client.Close()
collectionRef := client.Collection("CAR_COLLECTION")
// firestore.DocumentID == "__name__"
docSnap, err := collectionRef.Where(firestore.DocumentID, "==", collectionRef.Doc("001")).Get(ctx)
if err != nil {
log.Fatal(err)
}
// Unmarshall item
car := Car{}
docSnap.DataTo(&car)
car.ID = docSnap.Ref.ID
// Print car list
fmt.Println(car)
}
Just to clear confusion here
Remember, You should use async/await to fetch data whether fetching full collection or a single doc.
async function someFunction(){
await db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get();
}

Categories