Delete Firebase Child after 10 hours - javascript

I want to have a Function that deletes a 10 hour old child. I have this code so far but, if I deploy this to Firebase cloud functions it immediately removes all the data from the database. I am not sure what I'm doing wrong. Please help!
exports.deleteOldItems = functions.database.ref('Rollerbanken/{pushId}')
.onWrite(event => {
var ref = event.data.ref.parent; // reference to the items
var now = Date.now();
var cutoff = now - 10 * 60 * 60 * 1000;
var oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
return oldItemsQuery.once('value', function(snapshot) {
// create a map with all children that need to be removed
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null
});
// execute all updates in one go and return the result to end the function
return ref.update(updates);
});
});
My Firebase Database Structure:
{
"Rollerbanken" : {
"-Ku_Ywh8wElDdwNqa0KW" : {
"Extrainformatie" : "",
"Latitude" : "51.8306880305073",
"Longitude" : "5.90483402833892",
"Staater" : "Staat er nog steeds",
"Staaternietmeer" : "",
"Stad" : "Nijmegen",
"Tijd" : "19:50",
"TijdControle" : "19:50",
"TijdControleniet" : "",
"TypeControle" : "Rollerbank",
"TypeControle2" : "Rollerbank",
"postKey" : "-Ku_Ywh8wElDdwNqa0KW",
"timestamp" : 1506016223000
}
}
}

You have ref.orderByChild('timestamp') in your code, but there's no timestamp field in your data. This gets interpreted as having a null timestamp, which actually has the highest precedence in the ordering imposed by Firebase. As a result all your data nodes get ordered before the specified cutoff, and are removed.
To solve this, you need to add the timestamp field to your schema.

This how i code mine for 24hrs.
exports.deleteOldItems = functions.database.ref('/notification/{user_id}/{notification_id}').onWrite((change) => {
const ref = change.after.ref.parent; // reference to the parent
// For easier cross browser solution, get old time like this
const yesterday = Date.now() - 86400000; // that is: 24 * 60 * 60 * 1000
const oldItemsQuery = ref.orderByChild('time').endAt(yesterday);
return oldItemsQuery.once('value').then((snapshot) => {
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
// execute all updates in one go and return the result to end the function
});
});
Happy coding!

Related

NodeJS delete specific records when the date reaches 60 days

Good evening. Im Using JSJoda to calculate the difference between two dates. In the database there is a row where by default, the date is inserted automatically.
I need to create a normal function (without Req, Res object) where each row will be deleted after 60 days.
const cron = require('node-cron');
const JSJoda = require('js-joda');
const {deleteRecord, getAllMessages} = require('../connection/db.js');
exports.deleteMessage = async () => {
/**
* Get all the messages and delete statement
*/
const deleteStatement = 'DELETE FROM ?? WHERE ?? = ?';
const selectStatement = 'SELECT * FROM message';
try
{
const messageList = await getAllMessages(selectStatement);
/**
* Loop over the array of messages and find the date
*/
for (message of messageList) {
let dateTarget = message.dateAdded;
/**
* Convert the date to ISOString() and leave only the dates
*/
let messageDates = dateTarget.toISOString().split('T')[0];
let today = new Date().toISOString().split('T')[0];
let difference = JSJoda.ChronoUnit.DAYS.between(JSJoda.LocalDate.parse(messageDates), JSJoda.LocalDate.parse(today));
while (difference === 0) {
// Problem is here I dont know what should I do
await deleteRecord(deleteStatement, 'message', message.messageID, value);
}
}
}
catch (error)
{
console.log(error);
}
};
In this function I get all the records, and parsed it to the required format by the library. The variable bellow apparently shows the right days, But now I realised that I am stuck.
let difference = JSJoda.ChronoUnit.DAYS.between(JSJoda.LocalDate.parse(messageDates), JSJoda.LocalDate.parse(today));
I dont know how should I proceed with this function.... Where to place it, and the most important, how to select the right messageID that must be deleted.
This is the actual columns from MySQL

Not getting results from cloud functions by .where()

I am using this code to get data from a collection by comparing
/* eslint-disable */
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();
const database = admin.firestore();
exports.checkForPending = functions.pubsub.schedule('* * * * *').onRun(async (context)
=> {
var currentTime = admin.firestore.Timestamp.now();
var total; //getting time from firebase server
var firebase_time = admin.firestore.Timestamp.now(); // {'_seconds': 123456,
_nanoseconds: 123000000}
// Convert map of nanoseconds and seconds to milliseconds
var firebase_seconds_to_milliseconds = firebase_time._seconds * 1000; // 123456000
var firebase_nanoseconds_to_milliseconds = Math.round(firebase_time._nanoseconds /
1000000) //123
var milliseconds = firebase_seconds_to_milliseconds +
firebase_nanoseconds_to_milliseconds;
var firebase_month = firebase_time.toDate().getMonth();
var unix_to_date_before_buffer = new Date(milliseconds);
var unix_to_date_after_buffer = new Date(milliseconds);
// var unix_to_date = new Date(total);
unix_to_date_before_buffer.setSeconds(0); //coverted from 6:38:23 to 6:38:00
unix_to_date_after_buffer.setSeconds(0);
unix_to_date_after_buffer.setMinutes(unix_to_date_after_buffer.getMinutes() + 1);//coverted from 6:38:23 to 6:39:00
//Want to edit month in this timestamp;
const query =
database.collection("users").doc('IELTS').collection('IELTS').where("next", '>=', unix_to_date_before_buffer).where("next", '<=', unix_to_date_after_buffer); // comparing here
const snapshot = await query.get();
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data().name),
queryTest2 = database.collection('rest');
queryTest2.add(
{
'executed': true,
'name': doc.data().name
}
)
});
return null;
});
The am not getting any results in the console. I am wondering why?
I didn't see any new collection 'rest' formed.
The time in the collection of parameter 'next' was 6:38:24 in the collection in the example.
What I am trying to build -
I am making an app for an institute. I am registering users and making a collection which looks like -
collection
(here 'date' is the date of registration and 'next' is the time when The pay will automatically change to 0 because of the starting of next month.)
Now I am running a cloud function that is checking every day if 'next' is equal to the current time of server, then I want to execute something (add a user to a new collection called 'pending'.) and update 'next' to the next month. which should look like this -
edited-paramter

Is it possible to set limit for array in firestore?

i am planning to create an array of only 5 elements max in firestore like this
Array a = [1,2,3,4,5]
then add element 6 it will look like this
Array a = [2,3,4,5,6]
This cloud function (found here: https://github.com/firebase/functions-samples/blob/master/limit-children/functions/index.js) does what you want in Realtime Database:
'use strict';
const functions = require('firebase-functions');
// Max number of lines of the chat history.
const MAX_LOG_COUNT = 5;
// Removes siblings of the node that element that triggered the function if there are more than MAX_LOG_COUNT.
// In this example we'll keep the max number of chat message history to MAX_LOG_COUNT.
exports.truncate = functions.database.ref('/chat').onWrite((change) => {
const parentRef = change.after.ref;
const snapshot = change.after
if (snapshot.numChildren() >= MAX_LOG_COUNT) {
let childCount = 0;
const updates = {};
snapshot.forEach((child) => {
if (++childCount <= snapshot.numChildren() - MAX_LOG_COUNT) {
updates[child.key] = null;
}
});
// Update the parent. This effectively removes the extra children.
return parentRef.update(updates);
}
return null;
});
I believe you can adapt it for Firestore.

Firebase issue, I need to take out values from first two nodes

I try to achieve the following: When count is changed to "2" I need the function to push the JSON, named "updates", to the specific place in database, and take names from PlayerQueue node (0:"Mik", 1:"Bg" etc.) and put it into the database as "id". So the thing is that I need it to take first two nodes (0 and 1 in this case) and take names out of it (Mik and Bg) and put them in the database as id1 and id2 (in this database I have only one id value but I will add it later), the issue is that I can't figure out how to take out names from the first two nodes.
My database:
And here is my code
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { resolve } from 'url';
//Game/queue/{queueId}/PlayerCount
admin.initializeApp(functions.config().firebase);
exports.createGame = functions.database.ref('Game/queue/PlayerCount').onUpdate((change, context) => {
const ref1 = admin.database().ref('/Game/queue/PlayerQueue').limitToFirst(1);
var tmp:String = 'esh';
ref1.once("value")
.then(result => {
tmp = result.val();
console.log(tmp)
var updates = {};
updates['id'] = tmp
updates['visible'] = {
place: 'a1',
sign: 'rock'
};
const after = change.after.val();
if(after.count == 2){
return admin.database().ref('/Game/allGames').push(updates);
}
return null
}).catch(reason => {
console.log(reason)
});
return null;
});
Since you're looking for the first two child nodes in the queue, you should order by their ID and then limit to getting 2 children:
const query = admin.database().ref('/Game/queue/PlayerQueue').orderByKey().limitToFirst(2);
Then you can listen for the value:
query.once("value").then(snapshot => {
snapshot.forEach(child => {
console.log(child.key+": "+child.val());
});
});
The above purely solves the "getting the first two child nodes".
Update: to get the two children into separate variables, you can do something like this:
query.once("value").then(snapshot => {
var first, second;
snapshot.forEach(child => {
console.log(child.key+": "+child.val());
if (!first) {
first = child.val();
}
else if (!second) {
second = child.val();
}
});
if (first && second) {
// TODO: do something with first and second
}
});
Use Firestore unless you have a valid reason to use the Realtime Database.
See Cloud Firestore triggers documentation on how to take action .onUpdate to qty 2. See documentation example below
exports.updateUser = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
// Get an object representing the document
// e.g. {'name': 'Marie', 'age': 66}
const newValue = change.after.data();
// ...or the previous value before this update
const previousValue = change.before.data();
// access a particular field as you would any JS property
const name = newValue.name;
// perform desired operations ...
});

javascript sets - adding value to array in object inside a set

I'm trying to make an array of sets to make something like this
{
'user1': ["value#1", "value#2",..."value#N"],
'user2': ["value#2",..."value#N"],
'userN': [..."value#N"]
}
and then remove the value#x after 5 seconds (for example).
here is my code:
var myset = new Set();
var ran = myset[USERID] = commandNumber;
//i'm trying to make "if myset contains userNumber AND commandName" return,
//if its not, run someFunction() and continue
if (myset.has(ran)) return;
someFunction();
myset.add(ran);
setTimeout(() => {
myset.delete(ran);
}, 5000);
instead of getting output like the first code, i get this output instead
Set { 'command1', 'command2',
'USER1': 'command3',
'USER2': 'command4'
'USERN': 'commandN'
}
Feel free to comment if you have a question, so sorry if my question is hard to understand
A Set for this purpose is not necessary but I did a small POC that could help you to implement the solution you need:
'use strict';
const mySet = new Set();
const mySetMetadata = {};
const removeFromSet = (userKey, commandName) => {
const commands = mySetMetadata[userKey] || [];
if (commands.includes(commandName)) {
mySetMetadata[userKey] = commands.filter(c => c !== commandName);
if (mySetMetadata[userKey].length === 0) {
mySet.delete(userKey);
mySetMetadata[userKey] = undefined;
}
}
};
/**
* Add relation between an userKey and a command
* #param {String} userKey
* #param {Array} commands Array of commands
*/
const addToSet = (userkey, commands) => {
mySet.add(userkey);
if (typeof mySetMetadata[userkey] === 'undefined') {
mySetMetadata[userkey] = commands;
} else {
mySetMetadata[userKey] = [...mySetMetadata[userKey], ...commands]
}
}
// Populate with demo data
addToSet('user1', ['value#1', 'value#2', 'value#N']);
addToSet('user2', ['value#2', 'value#N']);
addToSet('user3', ['value#N']);
// Set up a timeout for a given user + key
setTimeout(() => {
removeFromSet('user1', 'value#2');
}, 5000);

Categories