Query by Date Range for a column field in Sequelize - node.js

I'm trying to query a database with Sequelize to get items that were created between a certain date range. I used the $between operator but I don't seem to be getting anything.
{ where: {"createdAt":{"$between":["2018-03-31T21:00:00.000Z","2018-05-30T05:23:59.007Z"]}} }
Can anyone help with how I can achieve this?

I also had the same problem, I was getting empty array in response. The problem got fixed using :
const Op = Sequelize.Op;
and then using [Op.between] as shown below:
where: {
createdAt: {
[Op.between]: ["2018-07-08T14:06:48.000Z", "2019-10-08T22:33:54.000Z"]
}
}
Hope it helps :)

$between syntax seems to be right. There are no issues with the way you used. I tried to replicate with the following query
model.findAll({
where: {
created_at: {
"$between": ["2018-03-31T21:00:00.000Z","2018-05-30T05:23:59.007Z"]
}
}
})
The only change is, I use created_at instead of createdAt. Make sure that your column name is right. If it is not, it should have thrown SequelizeDatabaseError. Look for it.
If everything else is right, then you might not be having data in that date range :)

Related

Search string value inside an array of objects inside an object of the jsonb column- TypeORM and Nest.js

the problem I am facing is as follows:
Search value: 'cooking'
JSON object::
data: {
skills: {
items: [ { name: 'cooking' }, ... ]
}
}
Expected result: Should find all the "skill items" that contain 'cooking' inside their name, using TypeORM and Nest.js.
The current code does not support search on the backend, and I should implement this. I want to use TypeORM features, rather than handling it with JavaScript.
Current code: (returns data based on the userId)
const allItems = this.dataRepository.find({ where: [{ user: { id: userId } }] })
I investigated the PostgreSQL documentation regarding the PostgreSQL functions and even though I understand how to create a raw SQL query, I am struggling to convert this to the TypeORM equivalent.
Note: I researched many StackOverflow issues before creating this question, but do inform me If I missed the right one. I will be glad to investigate.
Can you help me figure out the way to query this with TypeORM?
UPDATE
Let's consider the simple raw query:
SELECT *
FROM table1 t
WHERE t.data->'skills' #> '{"items":[{ "name": "cooking"}]}';
This query will provide the result for any item within the items array that will match exact name - in this case, "cooking".
That's totally fine, and it can be executed as a raw request but it is certainly not easy to maintain in the future, nor to use pattern matching and wildcards (I couldn't find a solution to do that, If you know how to do it please share!). But, this solution is good enough when you have to work on the exact matches. I'll keep this question updated with the new findings.
use Like in Where clause:
servicePoint = await this.servicePointAddressRepository.find({
where: [{ ...isActive, name: Like("%"+key+"%"), serviceExecutive:{id: userId} },
{ ...isActive, servicePointId: Like("%"+key+"%")},
{ ...isActive, branchCode: Like("%"+key+"%")},
],
skip: (page - 1) * limit,
take: limit,
order: { updatedAt: "DESC" },
relations:["serviceExecutive","address"]
});
This may help you! I'm matching with key here.

Loopback 4: Filter option

Loopback 4 allows to use an automatic/default filter that is really helpfull. My problem is that I want to use it in a customize way an I am not able.
Usual:
return this.customerRepository.findById(idCustomer, filter);
My Case:
I donĀ“t want to attack the "id" of the model, I want to attack another field. I have tried serveral things, but as a resume an example:
return this.customerRepository.findOne({where: { idUser: currentUserProfile.id }}, filter));
If I do that, the filter stop working. Any idea of how to mix a field in the model different than the id and the filter of loopback 4?
Thanks in advance
Best regards
#Jota what do you mean the filter stopped working? You have the correct idea about the approach. to search by a specific field just put it in the where clause as such:
this.customerRepository.findOne({ where: { <field_name>: <value_to_search> } })
e.g.
const filter = {
where: {
email: 'hello#world.com'
}
};
const result = await this.customerRepository.findOne(filter);

How to insert an Object into MongoDB

So I have an object using a dictionary to store products that a user has added to the cart in a shopping cart application. I am taking is object and attempting to insert into mongoDB with zero luck.
The piece of data I am attempting to insert looks like this:
products: '{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}}' }
My process of attempting to insert it into mongoDB looks like this:
db.orders.insert("products":{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}});
Currently with this approach I get the following error:
2016-12-15T18:11:43.862-0500 E QUERY [thread1] SyntaxError: missing ) after argument list #(shell):1:27
Which is implying there is some sort of a formatting issue with inserting it. I have moved quotation marks and parenthesis around plenty, simply to either get the above error, or a ... response from mongoDB implying that it is waiting for me to do something more to fix what exactly is causing an error.
Any chance anyone could help give some guidance in the best way to store this object in mongoDB?
My true question feels that it should have been in regards to the mongoose schema that would be used in order to store this data format. I hoped that getting how to initially insert it into mongodb was going to be enough but the way the data is being saved has me a bit confused. I know this is a bit of an awful question but could I get any assistance with setting up my schema for this as well?
"products" : {
"rJUg4uiGl" : {
"productPrice" : "78.34",
"count" : 2
},
"BJ_7VOiGg" : {
"productPrice" : "3",
"count" : 2
}
}
This is what the data looks like when it is stored in mongo. I think what is confusing me on how to set up is the "rJUg4uiGl" portion of the data. I am un-sure of how exactly that is suppose to look in mongoose schema. Here are a few of my rather poor attempts:
products: {
productId: {
productPrice: Number,
count: Number
}
}
Above simply doesn't store anything in the database
products: {
productId: [{
productPrice: Number,
count: Number
}]
}
Above gives:
"products" : {
"productId" : [ ]
}
Again, I know that this is quite specific but any help at all would be extremely appreciated.
Need to wrap your insert data in {}
db.orders.insert({"products":{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}}});

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.

Is there a simple way to make Sequelize return it's date/time fields in a particular format?

We need to have sequelize return dates in a particular format, not the default one. As far as I can tell, there is no way to set that up in options, or any other way. Short of manually updating the dates every time after they are retrieved, anyone been able to solve this easily? Or am I missing something?
You can, use the Sequelize fn method. From the API Reference, the fn function will help create an object representing a SQL function in your query.
For example:
model.findAll({
attributes: [
'id',
[sequelize.fn('date_format', sequelize.col('date_col'), '%Y-%m-%d'), 'date_col_formed']
]})
.then(function(result) {
console.log(result);
});
Will return data values:
[
{"id": 1, "date_col_formed": "2014-01-01"},
{"id": 2, "date_col_formed": "2014-01-02"}
// and so on...
]
21/06/2019
A little bit late but providing an update.
Sequelize is a powerful ORM (I am not saying is the best solution out there) but has a very bad documentation.
Anyway if you want to have this configured in your models one way apart from having to repeat this across your queries as other responses state you could be doing:
const Test = sequelize.define('test', {
// attributes
name: {
type: DataType.STRING,
allowNull: false
},
createdAt: {
type: DataType.DATE,
//note here this is the guy that you are looking for
get() {
return moment(this.getDataValue('createdAt')).format('DD/MM/YYYY h:mm:ss');
}
},
updatedAt: {
type: DataType.DATE,
get() {
return moment(this.getDataValue('updatedAt')).format('DD/MM/YYYY h:mm:ss');
}
}
If you are using dates to provide info as: last updated, first login, last login. This is the way to go.
The function get returns the new formatted element so it should not be restricted to dates either! Just bear in mind that this will slow your query so use cautiously. ;)
more info (i know i know but docs is the name of the game): https://sequelize.org/docs/v6/core-concepts/getters-setters-virtuals/
you can define custom instance methods getDate/setDate which would translate date between sequelize internal representation and desired format like so https://sequelize.org/master/manual/model-basics.html#taking-advantage-of-models-being-classes
If you are wondering to cast it as VARCHAR :
attributes:{include:[[sequelize.cast(sequelize.col('dob'), 'VARCHAR') , 'dob']],exclude:['dob']}
In case of Model that we create using Sequelize CLI
try something like this
var sequelize= require('../models');
model.findAll({
attributes: [
'id',
'title'
[sequelize.Sequelize.fn('date_format', sequelize.Sequelize.col('col_name'), '%d %b %y'), 'col_name']
]}.then(function(result))
{ // dateformate=04 Nov 2017
console.log(result)
}
visit this link for formate
To format Date, you can use Sequelize.fn method. I tried all mentioned methods but it won't work with date_formate. Try to create with bellow one.
model.findAll({
attributes: [
'id',
[sequelize.fn('FORMAT', sequelize.col('col_name'), 'yyyy-mm-dd'), 'col_name']
]})
.then(function(result) {
console.log(result);
});
here, i used 'FORMAT' instead of 'DATE_FORMAT', because it through error :
'date_format' is not a recognized built-in function name in api call.
For me, date_format and Format functions in above answers do not work.
I solved as below:
attributes: [
[sequelize.literal('date("dateTime")'), 'dateWithoutTime'],
],

Resources