I am working on a project where there are 2 databases (firestore) at same level.
One having user's profile and other has list of schedules.
Profile Db - user's email (stored as an array in the Db) , name, age.
Dates Db - user's email, time and date of schedule.
The function below matches user's email from the profile db with every email given in dates db and gives the list of dates having the same email.
DESIRED OUTPUT
startDateArr pushes the date records from dates Db so that the last date can be filtered and user can be informed of the last schedule.
ISSUE
I am unable to find the last date that is stored of the array.
let startDateArr = [];
db.collection('dates').onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
db.collection('profiles').get().then((querySnapshot) => {
querySnapshot.forEach((profileDoc) => {
if (profileDoc.data().userEmail[profileDoc.data().userEmail.length - 1] === doc.data().userEmail) {
let finalDate = `${ doc.data().startDate[ doc.data().startDate.length - 1 ] }
${ doc.data().startMonth[ doc.data().startMonth.length - 1 ] }`
startDateArr.push(finalDate);
}
})
})
})
})
Related
db structure
I am creating simple conversation app. I have three tables - users(id,name), conversations(id,user1_id, user2_id) and messages (id,conversationId,sender,message,date). Is there a way to actually get all user's conversations and data about another user in one query?
The query below gets id's of the user that logged user has conversations with. I would like now to get these users data base on their id. Thanks for all suggestions.
const getChats = (req, res) => {
const userId = req.params.userId;
db.query(
"SELECT DISTINCT CASE WHEN user1_id = ? THEN user2_id ELSE user1_id END userID FROM conversations WHERE ? IN (user2_id , user1_id)",
[userId, userId],
(e, r) => {
res.send(r);
}
);
};
module.exports = { getChats };
First, I'll answer the second question "how can get rid of doubling conversations where only conversation id differs and users are basically swapped?" to resolve this issue you need to check the conversation table before insertion by the below query
db.query(
"SELECT * FROM conversations WHERE (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)",
[senderId, receiverId,receiverId,senderId],
(e, r) => {
res.send(r);
}
);
if the above query returns a record then we'll not insert a new row.
now query for message with user data of a conversation
db.query(
"SELECT m.*,c.id,
s.name as "SenderUserName",
r.name as "ReceiverUserName",
FROM messages m
inner join conversations c on m.conversationId = c.id
inner join user r on r.id = c.user1_id
inner join user s on s.id = c.user2_id
WHERE (c.user1_id = ? AND c.user2_id = ?) OR (c.user1_id = ? AND
c.user2_id = ?)",
[senderId, receiverId,receiverId,senderId],
(e, r) => {
res.send(r);
}
);
the above query will return all messages between 2 users.
though you can remove the conservations table from the structure and it will be easy approach, here is the structure that i suggest
users table
name
type
id
int
name
varchar
messages table
name
type
id
int
message
text
sender_id
int
receiver_id
int
created_at
timestamp
I have two tables named in users and card_info in my Postgres database. I have created an endpoint for registering new users and I have given a field called dateCreated as shown in the code below.
Register.js
const handleRegister=(req,res,db,bcrypt,saltRounds)=>{
const {name,phno,dob,email,username,password,aadharCard}=req.body;
if(!name || !email|| !phno || !dob || !username || !password || !aadharCard){
return res.status(400).json('Wrong Form Submission');
}
const hash=bcrypt.hashSync(password,saltRounds);
const accNo=Math.floor(2E9+Math.random()*1E9);
const dateCreated=new Date().toJSON().slice(0,10);
db('users')
.insert({
username:username,
name:name,
email:email,
password:hash,
dob:dob,
phno:phno,
aadhar:aadharCard,
acc_no:accNo,
created_date:dateCreated
})
.returning('*')
.then(users=>{
res.json(users[0]);
})
.catch(err=>res.status(400).json("Unable to register"));
}
module.exports={
handleRegister:handleRegister
}
In the card endpoint, I am selecting the user's created year whose id is sent as a request. I then store these values into the card_info table using calculated values. The expiration date is supposed to be 4 years more than the created_year. The id of the table users is a foreign key of the table card_info
Card.js
const genCard=(req,res,db)=>{
const {id,cardType} =req.body;
db.select('created_date').from('users').where("id","=",id)
.then(data=>{
const createdDate=data[0].created_date.toString();
db('card_info')
.insert({
card_number:Math.floor(Math.random()*1E17),
owner_id:id,
expiration_date: createdDate.replace(parseInt(createdDate),parseInt(createdDate)+4),
cvv:Math.floor(Math.random()*1E3),
card_type:cardType
})
.returning('*')
.then(users=>{
console.log(res.json(users[0]));
})
.catch(err=>res.json(err.message))
})
.catch(err=>res.json(err));
}
module.exports={
genCard
}
This is the error that I recieve: "insert into "card_info" ("card_number", "card_type", "cvv", "expiration_date", "owner_id") values ($1, $2, $3, $4, $5) returning * - time zone "gmt+0300" not recognized".
I have tried various date formatting methods but nothing seems to work. Please let me know if someone has a solution to this.
I would avoid all the attempts to manipuate strings that represent dates–it only results in tears and often doesn't consider edge cases. Rather manipulate the date directly. I would recommend Luxon that provides a battled-tested wrapper around Date and has convenience functions that make dealing with dates easier.
// convert to DateTime object
const createdDate = DateTime.fromJSDate(data[0].created_date);
// add 3 months
const futureDate = createdDate.plus({months: 3});
// insert a date object
db('card_info').insert({
card_number:Math.floor(Math.random()*1E17),
...
created: futureDate, // or futureDate.toJSDate()
})
Demo:
const {
DateTime
} = luxon;
// convert a saved date from the DB to DateTime
const dt = DateTime.fromJSDate(new Date());
// add 3 months
const futureDate = dt.plus({
months: 3
});
console.info(futureDate.toFormat('yyyy-MM-dd'), futureDate.toJSDate());
<script src="https://cdn.jsdelivr.net/npm/luxon#2.0.2/build/global/luxon.min.js"></script>
I am having big difficulties in getting this done so I have to ask you guys for help now.
I am hitting the binance API endpoint for historical futurerates and I need all available data for every symbol in my array (from current to the very first created item).
The API offers query parameters and limits to do so "startTime" and "endTime" of type long timestamp in ms.
Here is the link to the docs
[fundingrate api endpoint[1]
[1]: https://binance-docs.github.io/apidocs/futures/en/#get-funding-rate-history
Using my approach, I am getting a bunch of results, but they randomly stop at some point in the past, so my pagination logic must be wrong. I just can not seem to find out where.
This is my current code
(async () => {
try {
const markets = symbols;
const targetDate = moment("2018-01-01"); //just one random past date I know it is for sure before any future contract creation on binance
for (let i = 0; i < markets.length; i++) {
let fundingRates = [];
symbol = markets[i];
let startTime, endTime, days_per_batch;
const initialResult = await binance.futuresFundingRate(symbol, { //make a request without a range to get a start and endpoint for pagination
limit: 1000,
});
startTime = moment(initialResult[0].fundingTime); //use the first retrieved item as startTime
endTime = moment(initialResult[initialResult.length - 1].fundingTime); //use last received item as endTime
days_per_batch = endTime.diff(startTime, "days"); //difference in days between first and last retrieved item of initial request
while (endTime.isAfter(targetDate)) {
const result = await binance.futuresFundingRate(symbol, {
startTime: startTime.unix(), //cast to timestamps
endTIme: endTime.unix(), //cast to timestamps
limit: 1000,
});
//concat retrieved result with result array that gets exported to csv
fundingRates = [].concat(
...result.map((e) => {
return {
symbol: e.symbol,
fundingRate: e.fundingRate,
fundingTime: moment(e.fundingTime),
};
})
);
//set the endTime to the previosu startTime and the startTime to startTime - days per batch (difference in days between first item and last item of result)
endTime = startTime;
startTime.subtract(days_per_batch, "days");
}
exportToCSV(symbol, fundingRates);
console.log("processing " + i + " / " + markets.length)
}
} catch (error) {
console.log(error);
}
})();
I have an app with two types of users - managers and employees. Also my app has groups. I have the following structure of the firebase database:
groups (collection) -> group (document)
Each group contains two collections managers and employees. Each document in both of the collections contains a field birthday. I want to send two types of notifications:
One to the employee to tell him happy birthday.
One to the manager to tell him that his employee/manager has a birthday today.
What I did:
exports.scheduledBirthday = functions.pubsub.schedule('0 8 * * *').onRun((context) => {
return admin.firestore().doc(`groups/{groupUid}/{usersCollection}/{user}`).get().then(userDoc => {
const userData = userData.data();
const birthday = userData.birthday;
const userFullName = userData.full_name
const birthdayDate = pasrseBirthday(birthday);
const currentDate = new Date();
if (currentDate.getDay() === birthdayDate.getDay() && currentDate.getMonth() === birthdayDate.getMonth()) {
console.log("Creating a birthday notification for: " + userFullName);
let tokens = userData.tokens;
const payload = {
data: {
notification_type: "USER_BIRTHDAY",
user_type: usersCollection,
title: "Happy birthday " + userFullName + "!"
}
};
return admin.messaging().sendToDevice(tokens, payload);
}
return null;
});
});
The code does as following: Set a scheduled crontab to 08:00 each day. It checks if the user's birthday is today. If it is, it will send a "Happy birthday" notification to that user (by executing the Android Java code).
As I mentioned before, I would like to send a notification to the manager if some employee or manager in his group has a birthday today. If there are some users with a birthday, it should send only one push notification (instead of sending for each one). In order to do it I thought of keeping an array variable usersBirthdays and push userData if the user has a birthday. In the last iterator of the loop I made, check if usersBirthdays is empty and if it's not, iterate over the managers and send the push notification. But I have some technical difficulties:
Is it the best way to do it? If not, how should I do it instead?
How can I know if we are in our last iteration of the firebase loop?
How should I iterate over the managers and send each one a push notifcation?
I found this method, with which I have ordered the hours what I store in my records, I wanted them to be sorted from highest to lowest, but when I test the code, I notice that only two values of the array are compared, which are the first registers.
I've seen other methods of comparison and the logic is the same, what am I doing wrong? I group the messages per user, using the id of the user as key of the array , then I save the rest of data. I do this for retrieve the current messages, since I want show a list of the last currently messages sent.
This is the code:
var ref = new Firebase('https://chatfbexample.firebaseio.com/all-messages');
ref.on("value", function (snapshot) {
var Messages = [];
var value = 0;
snapshot.forEach(function (snap) {
value = snap.val().id;
fecha = snap.val().id;
Messages[value] = [];
Messages[value]['fecha'] = snap.val().fechahora; //I receive a date with the format HH:MM:SS
Messages[value]['texto'] = snap.val().texto;
});
function compare(a, b) {
var time1 = a['fecha'].replace(/:/gi, '1');
var time2 = b['fecha'].replace(/:/gi, '1');
var data1 = parseInt(time1);
var data2 = parseInt(time2);
// alert(time1);
if (data1 > data2)
return -1;
if (data1 < data2)
return 1;
return 0;
}
Messages.sort(compare);
for (var i in Messages) {
console.log("Hour: " + Messages[i]['fecha'] + ' ' + ' Message: ' + Messages[i]['texto']);
}
});
the result is something like this
Hour: 12:11:13 Message: whats'up?
Hour: 11:38:44 Message: p
Hour: 11:49:01 Message: hey?
the second and the third messages are not being compared
an image of my Firebase database
First off it probably would be better for you to save a timestamp from Firebase instead of an actual time, which was probably created on the client side, inside your database. This way you could easily let Firebase handle the sorting.
You would need to use firebase.database.ServerValue.TIMESTAMP to save the exact time at which Firebase received your message inside fechahora.
Following you could simply query all of your messages ordered by their child fechahora.
ref.orderByChild("fechahora").on("value", function (snapshot) {
//Do stuff with your already sorted data
}
If you want your query to have a better performance set the .indexOn property of your node containing all the messages inside your Firebase Database rules to fechahora.
Bonus: If you want your data to be ordered newest to oldest instead of oldest to newest, you just need to use the negative value of the timestamp created by Firebase.
Instead of ordering client-side, you'll be better off asking the server to sort the messages:
ref.orderByChild("fechahora").on(...
Make sure that you define the proper index in your Firebase security rules:
{
"rules": {
"all-messages": {
".indexOn": "fechahora"
}
}
}
Without that the sorting will still work, but will happen on the client instead of the server.