Mongodb query Dates returning as String of numbers - datetime

for my MEAN stack project I have to store a Date object in MongoDB for the start and end of a booking. the Date goes in just fine, in my collection it's show as:
booking_start: 2022-12-16T00:00:00.000+00:00
booking_end: 2022-12-29T00:00:00.000+00:00
but when i query my collection for all entries the Dates come out as strings of numbers like this
"booking_start": "1671148800000",
"booking_end": "1672272000000"
what is going on here? I'll admit I'm new to working with Dates in Mongo but why is happening? I am using Graphql for my queries, but i don't think that the problem. is there a special way to query a Date?
here is my code and queries
resolver
getuserbooking: async ()=>{
const userListinglist = userbooking.find({})
return userListinglist
}
it's schema
type Query {
getuserbooking:[userbooking]
}
and it's mongoose model
booking_date:{
type: Date,
default: Date.now,
required:[true,"Please enter booking date"],
},
booking_start:{
type: Date,
required:[true,"Please enter booking start"],
},
booking_end:{
type: Date,
required:[true,"Please enter booking end"]
Please any help would be greatly appreciated

okay i figured out what went wrong, the numbers i kept getting back was a timestamp. i had to convert the timestamp into a Date so it could be displayed in the front end properly. if anyone else is having trouble with this here: https://bobbyhadz.com/blog/javascript-convert-milliseconds-to-date
hint: if your timestamp is a string use parseInt()

Related

findAll() returns empty with WHERE option

First question on StackOverflow, long time reader first time poster or whatever people say.
I'm developing a Discord bot in my free time using Discord.js, and I'm using Sequelize to interface with a local SQLite database. I can insert data into it just fine-- however, I can't seem to delete any of the records I add. Relevant piece of code is below, which I believe to be self-contradictory:
const query3 = await Towers.findAll({
attributes: ['channelID']
});
console.log(JSON.stringify(query3)); //returns the one Tower
console.log(query3[0].channelID === channel); //returns true(!)
const query2 = await Towers.findAll({
attributes: ['channelID'],
where: {channelID: channel}
});
console.log(JSON.stringify(query2)); //returns empty
//DELETE FROM Towers WHERE channelID = channel;
const query = await Towers.destroy({
where: {channelID: channel}
});
console.log(query); //returns 0, expected behavior given query2 returns empty
I'm attempting to delete a record from a table named Towers by passing a channel ID to it, which is expected to be unique. However, when I make any query on the database with a WHERE clause, the query returns an empty set-- even when, in this example, I sanity-checked and verified that the value I'm attempting to remove is present in the table. This occurs for both findAll() and findOne() as long as a WHERE clause is present.
(For posterity, I've double and triple checked that channelID was spelled correctly and with the correct capitalization in all instances.)
I'm happy to provide any more information if needed!
EDIT: As requested, the model definition...
const Towers = sequelize.define('Towers', {
serverID: {
type: Sequelize.INTEGER,
allowNull: false,
},
channelID: {
type: Sequelize.INTEGER,
unique: true,
allowNull: false,
},
pattern: Sequelize.STRING,
height: Sequelize.INTEGER,
delay: Sequelize.BOOLEAN,
});
channel in the snippet in the original post is defined as parseInt(interaction.options.getChannel('channel').id).
To anyone who happens to have the same issue I did, the answer is a doozy.
I wanted to store Discord server and channel ID's as integers, even though they're returned to you as strings when calling the API. As it turns out, Discord snowflakes are higher than float64 precision, which JS uses. When parsing the strings into integers to insert them into my table, the value changed from the intended number, and I was creating erroneous records.
In my case (with the actual numbers obfuscated) interaction.options.getChannel('channel').id returned "837512533934092340", while parseInt(interaction.options.getChannel('channel').id returned 837512533934092300. The number I was adding to the table was somehow 40 less!
I'm not sure if this could be fixed by using BigInt, but since it's going into a different structure anyway, I just shrugged and changed the serverId and channelId types to Sequelize.STRING in the model definition and removed the parseInt calls. Works like a charm now.
Good opportunity to shake my fist at JS though.

TypeOrm QueryBuilder dynamic auto delete function with crons job not working

Token for email verification is created with User registration and needs to be deleted from database within 24 hours with crons job help. In a delete function using query builder, token gets deleted only if date value is manually provided in form of string: {delDate: "2021-02-08T17:59:48.485Z" }. Here, all tokens with date before or equal 2021-02-08 get deleted, and is working fine. But thats a static input, manually put in hard code!
Since this must be a dynamic input, I set up variable 'delTime',which stores current date minus 24 hrs in it, but it seems .where condition will not take a variable as value, and will not delete, as: {delDate: deltime}. In fact, 'delDate' consoles exactly the info I need, but it will only work in form of string.
There is a ton of content online teaching how to delete stuff with a static value in typeorm querybuilder, but so hard to find with dynamic values....
How else can I make this work in a dynamic way ?
async delete(req: Request, res: Response){
try {
const tokenRepository = getRepository(Token);
var delTime = new Date();
delTime.setDate( delTime.getDate() - 1 );
console.log(delTime) //consoles 24 hors ago
await tokenRepository
.createQueryBuilder()
.delete()
.from(Token)
.where("tokenDate <= :deleteTime", { deleteTime: delTime})//value dynamically stored in variable does not delete
//.where("tokenDate <= :deleteTime", { deleteTime: "2021-02-08T18:01:10.489Z"})//static hard code value deletes
//.where("tokenDate <= :delTime", { delTime})//Variable put this way will not work either...
.execute();
} catch (error) {
res.status(404).send("Tokens not found");
return;
}
res.status(200).send('Tokens deleted successfuly');
}
Your parameterized query looks correct.
Switch on TypeOrm Query Logging to see the generated SQL, maybe you will be able to see what's going wrong. Paste the generated SQL into the SQL query console to debug.
Alternatively you can write your delete query without parameters and let Sqlite calculate current date -1 day:
.where("tokenDate <= DateTime('Now', '-1 Day'"); // for Sqlite
Note 1: Sqlite DateTime('Now') uses UTC time, so your tokenDate should use UTC also.
Note 2: This syntax is specific to Sqlite, you can do the same in other databases but the syntax is different, e.g. Microsoft SQL Server:
.where("tokenDate <= DATEADD(day, -1, SYSUTCDATETIME()); // for MS SQL Server

How to add timestamp on document create to Firestore from Flutter [duplicate]

This question already has answers here:
Flutter Firestore Server side Timestamp
(4 answers)
Closed 2 years ago.
I am writing code to set data to Firestore from flutter. What I want is to add a field for the time the data is created, eg "createdOn". DateTime.now() for Flutter takes the time from the device but I would like to get the serverside time. My code is as below:
Future updateDataModel(String userName, String userPosition, String userLocation) async{
return await userCollection.document().setData({
'userName' : userName,
'userPosition' : userPosition,
'userLocation' : userLocation
});
}
It would be a great help if I could have a field like below that gets the timestamp for firebase.
'createdOn' : TimestampHere,
You can use the FieldValue.serverTimestamp()
serverTimestamp(): FieldValue Returns a sentinel used with set() or
update() to include a server-generated timestamp in the written data.
'createdOn':FieldValue.serverTimestamp()
References
ServerTimestamp
you can use several types of time stamp ,example date time
"timestamp": DateTime.now(),
server value
'timestamp' : Timestamp.now()
If you are using Firebase,you should store the timestamp from epoch like that
DateTime.now().microsecondsSinceEpoch

How to use startAt() in Firebase query?

Let's suppose above firebase database schema.
What I want to is retrieve messages which after "15039996197" timestamp. Each of message object has a createdAt property.
How can I get messages only after specific timestamp? In this case, last two messages are what I want to retrieve.
I tried firebaseb.database().ref(`/rooms/$roomKey/messages`).startAt('15039996197') but failed. It return 0. How can I do this?
The case with your query is that it's expecting that the message node should have a number value to start with, in that case you want a child node with the name createdAt. So in that case you must specify that you want to order by createdAt, thus you need to do this
firebase.database().ref(`/rooms/$roomKey/messages`).orderByChild('createdAt').startAt('15039996197').on(//code);
This way it'll return all nodes inside message that has a child named createdAt an it starts at 15039996197. Ordering your query may be a little bad for performance, for that i sugest taking a look at .indexOn rule.
For more information take a look here.
Hope this helps.
Firebase Data Retrieval works node by node.
So whatever data you want to get, the entire node is traversed.
So in your case to get any message your complexity would be O(number of messages).
You would want to restructure the way you are storing the data and put createdAt in Node instead of Child.
If your database structure looks like that, you can use:
firebase.database()
.ref(`/rooms/$roomKey/messages`)
.orderByChild('createdAt')
.startAt('15039996197').on('value', snapshot => { /* your code here */ });
But if you work with a lot of data entries, you can also name the item key with the timestamp, instead of storing the timestamp in your data. This saves a little data on your database.
firebase.database().ref(`${rooms}/${roomKey}/${timestamp}`).set("value");
To retrieve the data in that case instead of orderByChild('createdAt'), you'll use orderByKey(). Because firebase keys are of the string type, you need to make shure to parse the timestamp in the .startAt() to a string.
It will then look something like this:
firebase.database()
.ref(`/rooms/$roomKey/messages`)
.orderByKey()
.startAt(`${15039996197}`).on('value', snapshot => { /* your code here */ });
You can do something like that:
firebase.database().ref('/rooms/$roomKey/messages')
.orderByChild('createdAt')
.startAt('150399')
.endAt('1503999\uf8ff')
.on('value', function (snapshot) {
var key = snapshot.key,
data = snapshot.val();
console.log(key + ': ' + JSON.stringify(data))
});
Be sure to set endAt().

How to parse a collection's sub-object to find a unique result from many possibilities?

In my user's schema, I have a TokAuth Array with token sub-objects (like multiple mails addresses).
So in a method, when I search the tokens in the current user :
var id = Meteor.userId();
var usercurrent = Meteor.users.findOne({_id: id}, {fields: {"TokAuth": 1}});
var userToken = usercurrent.TokAuth.token;
I got in console.log(userToken)
[ 'fyAyXkXYrQdAlNpjuQfJ8RLU2TpfVGLnptlBs-m1h7xk',
I20170224-20:36:23.202(1)? 'YTwtUbhNTgiEfzFbJq7mESnOoOHeLYxWlqEeJJIG_GiV',
I20170224-20:36:23.206(1)? 'ViA4ydDITJtHDi2c_sArkNtpRYTjFqGL1ju2v00_-rFJ',
I20170224-20:36:23.206(1)? '51ImZcxRADLJr-FPCUL7EFGnTZYjHSZk3XxdqtBV2_fd',
I20170224-20:36:23.207(1)? 'S5aEvqjJ5zTUJqLFCPY1aZ1ZhsQppZTJtYKULM9aS2B3',
I20170224-20:36:23.207(1)? 'mhBs3oxHf2SxZfu2vCZhtiyPfg25fKMY8bKMZD8fx6IG',
I20170224-20:36:23.207(1)? '-rv0FiP-lxoqe8INyCJASV6rZpbgy3euEqB9sO9HsZSV',
I20170224-20:36:23.207(1)? 'zacr6_VBjHTsArov1LmQyZFLwI40fx4J7sygpLosTrli' ]
Beside, I've got a var who is equal to the last token in the userToken sub-object (that's of course expected : not to be the last one, but to be in the sub-object).
console.log (editAuth);
zacr6_VBjHTsArov1LmQyZFLwI40fx4J7sygpLosTrli
So how can I parse userToken to find a match with editAuth? If userToken was just a String, it will be simple but here...
Thanks
Is there a reason you are storing all the tokens as an array as opposed to just updating a single string each time?
That aside, you can check if an array contains a value by using the handy underscore function _.contains
Example:
_.contains( userToken, editAuth ); //returns true or false
In this case, you are simply trying to search for a string within an array of strings. #Sean already provided one solution.
If you are using the meteor ecmascript package then you can just simply use the native Array.includes method.
userToken.includes(editAuth);
On a side note, after using ECMAScript 2015+ for some time now, I find that I can use the native API for almost everything that I used to use underscore or lodash for. Check it out!

Resources