Nestjs/Prisma not saving date number correctly - node.js

When I console log the response body right before I save it to the database, my response body shape looks correct. See below
//console.log response body
CreateOpenHourDto {
day: 'WEDNESDAY',
startTime: 1663858800000,
endTime: 1663878600000,
calendarId: 1
}
However, whenever I go into prisma studio and check the new db entry, the startTime, endTime is differnt.
There is nothing I have done to transform the data. Any tips are appreciated.
I am using
nestjs, prisma, postgres sql

My prisma model listed start and end times as "int" types and it should have been BigInt. For anyone that plans on using bigint. Be aware
Prisma returns records as plain JavaScript objects. If you attempt to use JSON.stringify on an object that includes a BigInt field, you will see the following error:
Do not know how to serialize a BigInt
To work around this issue, use a customized implementation of JSON.stringify:
JSON.stringify(
this,
(key, value) => (typeof value === 'bigint' ? value.toString() : value) // return everything else unchanged
)
This sounds hacky but its coming straight form the documentation as of the time of this comment.
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields#working-with-bigint

Related

How to pass date as an input to SQL Server query in node

I am using node-mssql and my function goes like this:
const getPoliciesDue = async (userId, toDate) => {
const db = await sql.connect(config) // const sql = require('mssql'), config = {config for my DB}
const request = db.request()
.input('userId', sql.VarChar, userId) // userId is a string
.input('toDate', sql.Date, toDate) // toDate is a javascript Date() object
const result = await request.query(
'SELECT policyNumber, holderId, ... FROM Policies WHERE Policies.userId = #userId AND Policies.toDate <= #toDate'
)
return result.recordset
}
I want to get all the policies which are expiring before a certain date belonging to a certain user.
But when I run this exact query, I get the error
Must declare the scalar variable #userId
I removed #userId from the WHERE clause and put '#toDate' (quotes around the variable). Now I get an error
Conversion failed when converting date and/or time from character string
The documentation says input() accepts the Date() object. I have tried passing date object as well as a string in YYYY-MM-DD format, but with no avail. Passing a string in YYYY-MM-DD format works for an INSERT query, but not for a SELECT query. How am I supposed to run my query?
Note I can't run the query in a single line, like
db.request().input().query()
because there is another input which will later go in conditionally.
Okay, a huge oversight on my part and sincere apologies to those who tried to find an answer. I found out that I was running the query() method on the wrong object. I was running the query method on db object whereas I should have run it on the request object. The code works perfectly after calling the method on the right object.

Is it possible to refer to "this" document in Mongoose?

I'm using Mongoose in Node.js, and I am wondering if it is possible to refer to the currently selected document using "this" or a similar mechanism. Here is the use case I'm looking for :
Mongoose Schema :
const mySchema = mongoose.Schema({
position: Number,
date: Number,
lastEventDate: Number
});
Let's say that, at some point in time, an event occurs.
For a document selected through its position, I want to update "lastEventDate" to the document's date.
Here is my dream code :
myModel.findOneAndUpdate(
{position: myPosition},
{$set: {
'lastEventDate': THISDOCUMENT.date
}}
);
Note : I'm using $set here because the actual code updates subdocuments...
Is there a built-in "THISDOCUMENT" reference such as the one I'm dreaming of, to do it all in a single query ?
Or do I have to first query the value before updating the document (two queries).
Couldn't find anything on the web, and I'm quite the newbie when it comes to using "this".
Thanks for any kind of help !
[EDIT :] Precisions about the objective :
I am in a situation where I only have the position "myPosition" to identify the correct document, and I want to set "lastEventDate" to the same value as "date" for that document.
My question is about efficiency : is it possible to perform the update in a single upload query ? Or do I have to first download the "date" value before uploading it back to the "lastEventDate" key ?
Gathering all the information provided, I will venture on a possible answer!
You could try something like:
Your schema JS file
const mySchema = mongoose.Schema({
position: Number,
date: Number,
lastEventDate: Number
});
mySchema.methods.doYourThing(){
this.lastEventDate=this.date; //it will set the lastEventDate
}
mongoose.model("myModel", MySchema, "mycollection")
Now, whenever you call doYourThing(), the action wanted will take place, you call it after you have a instance of the mode.
This is from my own code
const token = user.generateJwt(expirationDate); //send a token, it will be stored locally in the browser
it is inside a function that return an instance of user, and in the model User I have done a function called generateJwt like I have showed, and we have something like this:
return jwt.sign(
{
_id: this._id, //this is created automatically by Mongo
email: this.email,
name: this.name,
exp: parseInt(expiry.getTime() / 1000, 10), //Includes exp as UNIX time in seconds
level: this.level,
lastLogin: this.lastLogin,
failedLogin: this.failedLogin
},
process.env.JWT_SECRET
); // DO NOT KEEP YOUR SECRET IN THE CODE!
It returns all the information of the user!
Please, do not hesitate to add comments and feebacks, I am not sure it is what you want, but that is why I have understood your request.
Anothe option is using Virtuals, they also have access to this.

how to use datetime in sails model

i would like to have a function in my controller to get data based on time range. First, i have all the data in mongodb, there is a attribute ModifiedTime as string looks like 2015-02-25T17:17:33Z. Second, i define the model in sails with ModifiedTime:
{ type: 'datetime', columnName: 'ModifiedTime' }
In the model.js, I set schema: true. Then in my controller, i try to use
User.find({ModifiedTime : {'<=' : new Date('2015-03-18T00:00:00Z')}}).exec(function(err,st){
if (err) return res(err);
if (!st) return res(new Error('Invalid ModifiedTime.'));
return res.json(st);
} );
But i get nothing, see always [] in the browse. I used waterline http://localhost:1337/User to check the data in browse. i can see all the data from mongodb. The strange thing is, i see something like ModifiedTime": "2015-02-18T17:36:53Z. so, for me, it looks like the ModifiedTime in sails is still a string, am i right? but i set the type as datetime in the model. I hope, it could transfer the string of mongodb to datetime in background, won't it? Please give some advise. i spend already too much time for that :(
thank you very much!
WJS
You're right / wrong.
In your DB you state the datetime is a string. If it is already a string then you can't set it to be a date in your sails model. You should simply compare two strings instead of transforming 2015-03-18T00:00:00Z into a date.
User.find({ModifiedTime : {'<=' : '2015-03-18T00:00:00Z'}}).exec(function(err,st){
if (err) return res(err);
if (!st) return res(new Error('Invalid ModifiedTime.'));
return res.json(st);
} );
If you truley want to use Date/Time then you must go through your original data and change modified time to a date/time object.

Sequelize - always return arrays even when only one record is retrieved

I'm using Sequelize with Postgres and Angular.js in the front-end.
I'm setting up some routes to expect arrays in the response:
'getData': {
method: 'GET',
// isArray: true,
url: 'stuff/:id',
params: {id: '#id'}
}
However, when only one record is retrieved Sequelize seems to return an object directly
rather than an array with one object in it, which breaks the resource:
Error in resource configuration. Expected response to contain an array but got an object
Is there a way of setting up Sequelize to always return arrays even if there's only one record retrieved?
Or, a clean way of wrapping the data when it gets to ng-resource?
Thanks!
Angular should support object responses, but in any case:
Model.find() will return an object, Model.findAll() will return an array. You can just swap to using a findAll, if filtering on primary key it won't make much of a difference.
Model.find() also takes query parameters as it's second parameter so you should also be able to do Model.find({where: ..}, {plain: false}) but that hasn't been tested and isn't exactly public API.

Wide rows in Cassandra using CQL - getting weird error

I'm trying to store comments for a blog in Cassandra and have come up with this schema (got the idea from here):
create table comments ( slug varchar, ts timestamp, value text, primary key (slug,ts));
Using CQL (I'm using node.js with Helenus driver) I'm trying to add some data to it, here's what I've got so far:
var helenus = require('helenus'),
pool = new helenus.ConnectionPool({
hosts: ['localhost:9160'],
keyspace: 'blogks'
});
pool.on('error', function(err) {
console.error(err.name, err.message);
});
module.exports.addComment = function(slug, comment,callback){
pool.connect(function(connErr,keyspace){
if(connErr){
callback(connErr);
return;
}
var cql = "INSERT INTO comments (slug,ts,value) VALUES (?, ?, ?);";
pool.cql(cql,[slug,serializeDate(new Date()),serializeJSON(comment)],function(err,results){
callback(err,results);
});
});
}
function serializeDate(date){
var dateSerializer = new helenus.Marshal('DateType');
return dateSerializer.serialize(date).toString('hex');
}
function serializeJSON(data){
var utf8Serializer = new helenus.Marshal('UTF8Type');
return utf8Serializer.serialize(JSON.stringify(data)).toString("hex");
}
The idea being you can pass in a comment json object to this method, and push it to cassandra. I'm calling it like this to test:
var comments = require('./comments.js');
comments.addComment("myslug",{id:2,name:"Alex",comment:"Hello!"},function(e,r){
console.log(e);
console.log(r);
})
but whenever I do (I tried various CQL drivers), I get this cryptic error message:
[HelenusInvalidRequestException: unable to coerce 'value' to a formatted date (long)] name: 'HelenusInvalidRequestException'
I tried changing the timestamp to be all different data types, but no luck. The very strange thing is that at first, my primary key was just the slug itself, and then it did work. However, I want to store all comments in one row ordered by timestamp, therefore I had to go with this approach of using two columns for the primary key. Any ideas?
EDIT So based on rs_atl's suggestion, here's what I've tried:
This line:
dateSerializer.serialize(date).toString('hex')
did in fact return garbage (0000013ccfacf5c4), I must have misunderstood how to use the API. So here's what I tried instead:
I tried just new Date().getTime() which in JS does in fact return Unix-style epoch, but that didn't work I got the same error. I then tried using moment.js to try and format the string:
moment().format("YYYY-MM-DD HH:mm:ss")
which seems to be returning the correct format, but again. Same error. Then I tried this:
moment().format("YYYY-MM-DD HH:mm") + "Z"
no luck. I then tried this:
moment().format("YYYY-MM-DD HH:mmZ")
which does in fact add the timezone info at the end, but still, no luck. Any ideas?
it seems you are using the wrong CQL version. You expect to use CQL 3.0.0 but the driver defaults to CQL2. You need to specify the correct CQL version in the initialization.
pool = new helenus.ConnectionPool({
hosts: ['localhost:9160'],
keyspace: 'blogks',
cqlVersion: '3.0.0'
});
And also please ensure you are using the latest version (0.6.2 as of now) of Helenus.
I'm not exactly sure what the output of this line is:
return dateSerializer.serialize(date).toString('hex');
but this is where your issue is. It appears that you are not outputting a valid date that Cassandra understands. A valid date is either:
A Unix-style epoch as a long value.
A string in one of the following forms:
yyyy-mm-dd HH:mm
yyyy-mm-dd HH:mm:ss
yyyy-mm-dd HH:mmZ
yyyy-mm-dd HH:mm:ssZ
yyyy-mm-dd'T'HH:mm
yyyy-mm-dd'T'HH:mmZ
yyyy-mm-dd'T'HH:mm:ss
yyyy-mm-dd'T'HH:mm:ssZ
yyyy-mm-dd
yyyy-mm-ddZ
Check to make sure you are writing one of these valid timestamp types.
For timestamps, I've always use int in milliseconds to represent time.
Try:
Date.now()
instead of:
serializeDate(new Date())

Resources