I am using AngularFire2 with ionic 2 and storing the data in webSqlStorage.
When I complete the the first GET it saves it to storage. What I want to do is if the user has a connection then check the data from Firebase, if it has not changed, then get the local data, else get the updated data.
Currently, I have a simple check to see if there the storage is not null which then gets the local data, but this will not work for production.
let loader = this.loadingCtrl.create({
content: 'Getting Programs...'
});
loader.present().then(() => {
this.storage.get('programs').then((data) => {
if (data != null) {
loader.setContent("Getting Local Data...");
this.programs = data;
} else {
this.yApi.getPrograms().then(data => {
this.programs = data;
this.storage.set('programs', data);
},err => {
// Probaly offline with no local data
console.log("Err is to human");
});
}
}).then(() => {
loader.dismiss();
});
});
Just wondering if there is a way to write something like
if (data != null || this.af.checkUpdated('/programs')) { ...
or something.
I used an additional database value like program_version in my projects. If firebase program_version is greater than the local storage, than update. On every program update your program_version will be increased or set a timestamp.
Related
Im trying to do something absurderlly simple but this whole IAM, Realtime Database, cloud functions misconfiguration are making me waste hours of work in something simple as a hello world.
I have an already populated database (over 300 items):
then i have the following function deployed to firebase cloud:
const actions = [];
const igDatabase = require('firebase-admin').initializeApp({
serviceAccountId: 'actionkeeper#igibo-b0b27.iam.gserviceaccount.com'
}).database("https://igibo-b0b27.firebaseio.com/");
let lastMapRefresh = 0;
let lastUpdateFirebase = 0;
function refreshActions(afterRefresh) {
console.log("refreshing actions");
igDatabase.ref('actions/').orderByChild('timestamp').startAt(lastMapRefresh).once('value').then(function(data) {
if (data != null && data.exists()) {
let bef = actions.length;
actions.length = 0;
actions.push(data.val());
lastMapRefresh = new Date().getTime();
afterRefresh();
}
console.log("actions refreshed before: " + bef + " now: " + actions.length);
}).catch(function(error) {
console.error("Error: " + JSON.stringify(error));
});
}
exports.decrementAction = (req, res) => {
refreshActions(function() {});
}
this function is simple reading a branch on database and populating an array... the purpose of the functio is more complex but im building it and testing slowly... and even this simple method is not working
the firebase rules for that node is:
{
"rules":{
"actions":{
".indexOn":[
"timestamp"
],
".read":"auth != null",
"$act":{
"countdown":{
".write":"auth != null && data.val() - newData.val() == 1 && newData.val() >= 0"
}
}
}
}
}
so ANYBODY logged can read
in the google IAM console i have
so the service account is supposed to have admin powers to database...
but running this function ALWAYS RETURN NULL data
why?
Your code doesn't appear to actually send a respond to the client. Here's your function:
exports.decrementAction = (req, res) => {
refreshActions(function() {});
}
Not once does it ever use res to send a response. It's always going to time out after the default 60s, stuck waiting for you to call res.send() or something similar.
I suggest reviewing the documentation on HTTP triggers to see how to send a response. I imagine your (currently empty) callback function needs to do this, based on what refreshFunctions delivers to it.
I am retrieving data from cloud firestor in componentDidMount() method, but when fetching starts and during fetching data from cloud firestor I am not able to change tab, it takes 8 seconds for less than 100 items docs.
I am using react-navigation and cloud firestor in react-native app.
Even from cache it takes 8 seconds and I couldnt change tabs during fetching data from cloud firestor, but after fetching I am able to change tabs.
getMessages(){
db.collection("users/" + this.state.username + "/msgs").orderBy("date", "asc").get().then(snapshot=>{
this.docs = snapshot.docs;
for (let i = this.docs.length - 1; i >= 0; i--) {
this.prtcpnts = this.state.currentuser === this.docs[i].data().user.username ? this.state.currentuser + this.docs[i].data().otheruser : this.state.currentuser + this.docs[i].data().user.username;
if (this.state[this.prtcpnts] === undefined){
this.setState({
[this.prtcpnts]: [this.docs[i].data()]
});
}else{
this.setState(preState => ({ [this.prtcpnts]: [...preState[this.prtcpnts], this.docs[i].data()] }));
}
}
});
}
I want to fetch smothly without stopping my app, I mean I should be able to change tab even during fetching data from cloud firestor.
I solved my problem by refactoring to the following code.
if (this.outState[this.prtcpnts] === undefined){
this.outState[this.prtcpnts] = [this.docs[i].data()];
}else{
this.outState[this.prtcpnts] = [...this.outState[this.prtcpnts], this.docs[i].data()]
}
if (i === 0) {
this.setState({ ...this.state, ...this.outState })
}
I'm having issues adding data to firestore. I can upload my data with no problem if the URL reference from firestorage isn't in the data set. I've even uploaded blank document to firestore with no problem. I was able to upload the data about 3 months ago and now it won't work.
dbRef = firebase.firestore().collection('Collection');
const inputInfo = new GeoFirestore(dbRef);
inputInfo.add({
coordinates: new firebase.firestore.GeoPoint(this.state.latitude, this.state.longitude),
mainPhotoURL: this.state.mainPhotoURL,
address: this.state.address,
nickName: this.state.nickName,
firebaseID: this.state.firebaseID,
}).then((docRef) => {
console.log(docRef.id); // ID of newly added document
console.log(docRef);
}, (error) => {
console.log('Error: ' + error);
});de here
If I take out mainphoto URL then it will upload. If I put it in the data set then it won't add to the database. I've console logged the mainphoto object and there is data inside of it. Has anyone run into this issue before?
According to my initial read of the documentation, It appears that you put coordinates only in the geoFirestore. Put your metadata such as nickname in a separate collection/document with a pointer to the geoFirestore uid.
A GeoFirestore instance is used to read and write geolocation data to
your Firestore database and to create queries.
geoFirestore.set({
'some_key': { coordinates: new firebase.firestore.GeoPoint(37.79, -122.41)},
'another_key': { coordinates: new firebase.firestore.GeoPoint(36.98, -122.56)}
}).then(() => {
console.log('Provided keys have been added to GeoFirestore');
}, (error) => {
console.log('Error: ' + error);
});
In my app I pushed some object to my firebase-database and immediately after that (after the then-promise fully filled) I fetch the object (with the returned key) from the database (with the on-value method).
In addition, I make some changes on the pushed object using the firebase-functions.
How can I receive the object (in the app) just after the changes and not before? (like other ordinary backend services)
I hope this helps you, I have not tested this piece of code but it should help you in the right direction.
Also dont use this exact code in production, there is plenty room for improvement, this is just an example code.
exports.testFunction = functions.https.onRequest((req, res) => {
if (req && req.body) {
if (
req.body.hasOwnProperty('name') &&
req.body.hasOwnProperty('age')
) {
const person = {
name: req.body['name'],
age: req.body['age']
}
// Make some changes to the person object
person['hobby'] = 'Programmer';
// Add object to FireStore
admin
.firestore()
.collection('/persons')
.add(person)
.then((success) => {
// Return the added & changed person
res.status(201).send(JSON.stringify(person));
})
.catch((error) => {
// Error
console.error('Something broke', error)
res.status(500).send();
});
}
else {
// Error
res.status(500).send({err: 'Missing property'});
}
}
else {
// Error
res.status(500).send({err: 'Missing something'});
}
});
I have my DB in Firebase but I want to do a WHERE, as a login (i.e. if I enter the user and the password, it brings me the user's corresponding data).
This is my DB in firebase:
An example:
When I send the email and telefono to tb01_usuario bring me the corresponding data:
Currently I am doing it only with the ID that is similar to the field telephone, but I need to do it with the two fields that are inside each record, I hope they understand me
verifica_usuario(telefono: string,email : email ) {
email = email;
telefono = telefono;
let promesa = new Promise((resolve, reject) => {
//this.items = afDB.list('/cuisines');
this.af.list('/tb01_usuario/' + telefono + email )
.subscribe(data => {
if (data.length === 0) {
//clave no es correcta
resolve(false);
} else {
//clave correcta
this.telefono = telefono;
this.guardar_storage();
resolve(true);
}
});
})
.catch(error => console.log("ERROR en promesa Service: " + JSON.stringify(error)));
return promesa;
}
You can't do that directly in Firebase.
As per Firebase docs
The Realtime Database API is designed to only allow operations that can be executed quickly.
You should structure your data in a way that you can easily fetch what you need.
What you might want to use is either redundant nodes (similar to what MarianoCordoba mentioned), which is replicating data in a way that makes it easier to access what you need, or indexOn (documentation) and orderByChild([CHILD_NODE]).equalTo([QUERY]) (documentation). Note that you can also use orderByKey() and orderByValue(), which allow you to filter/sort your data (which is what I'm assuming you mean by using WHERE in Firebase).