Mimic where [condition] between [colA] and [colB] sequelize - javascript

Looking for assistance in replicating the following mssql operation in sequelize. We have a table with a valid_from and valid_to columns and I need to get todays current date and only return the records that are fall based on that.
I am looking to utilize the .findByPK(), or .findAll() methods in sequelize
SELECT * FROM [table] WHERE GETUTCDATE() BETWEEN f.valid_from AND f.valid_to
I have found the following posts and items with no luck. As they seem to specify two di9ffernt dates between the same column. I need to compare the current UTCDATE between two different columns
Sequelize Query to find all records that falls in between date range
Sequelize query - compare dates in two columns
I was able to simulate but would still like to know if anyone knows how to do the same thing using the between operator
const now = new Date();
return await models.Form.findAll({
where: {
valid_from: {
[Op.lte]: Sequelize.cast(now, 'DATETIMEOFFSET')
},
[Op.and]: {
validTo: {
[Op.gte]: Sequelize.cast(now, 'DATETIMEOFFSET')
}
}
}
});

You can write this query using sequelize.where() to generate the WHERE statement for the BETWEEN operation. For the current timestamp you need to call GETUTCDATE() which we can do via sequelize.fn().
const forms = await models.Form.findAll({
where: {
// create where condition for GETUTCDATE()
sequelize.where(sequelize.fn('GETUTCDATE'), {
// BETWEEN valid_from AND validTo
[Op.between]: [
sequelize.col('valid_from'),
sequelize.col('validTo')
],
}),
},
});
This will generate SQL like:
SELECT * FROM `form`
WHERE GETUTCDATE() BETWEEN `valid_from` AND `validTo`
note that you have underscored valid_from and camelCase validTo in your example.

Related

get a range of numbers from sql column of type varchar

I have a postgres server running with one column (say marks) of type VARCHAR(255), but is supposed to have numbers, like if i do a select *.. query , i will get ['100','50','21','14'...] etc.
i would like to run a range query on it, like user passes [10,30] and gets ['21','14'] as result. I think this would require casting at the time of running the BETWEEN query, but i cannot get it to work properly.
I am using sequalize.js which is generating the following query:
SELECT "id"
FROM "token_attributes" AS "token_attributes"
WHERE "token_attributes"."attributesDirectoryId" = 3
AND CAST('token_attributes.attributeValue' AS INTEGER) BETWEEN 10 AND 30;
on server also this query seems to fail. the sequalize query that is being created is :
{
where: {
attributesDirectoryId: 3,
attributeValue: Where { attribute: [Cast], comparator: '=', logic: [Object] }
},
attributes: [ 'id' ]
}
i have used the following code to create the where condition (cast and where were imported from sequelize):
let whereFilter ={}
let value = where(cast(`${tableName}.attributeValue`, 'integer'), {[Op.between]: rangeAsInt})
whereFilter['attributeValue'] = value
so this is basically calling table.findAll({where:whereFilter}) I am not sure how to either make sequelize create a correct sql api or what the actual correct SQL api would be. can anyone help?
found the issue, i missed the sequilize.col function :
let whereFilter ={}
let value = where(cast(col(`${tableName}.attributeValue`), 'integer'), {[Op.between]: rangeAsInt})
whereFilter['attributeValue'] = value
and the query would be :
SELECT "id"
FROM "token_attributes" AS "token_attributes"
WHERE "token_attributes"."attributesDirectoryId" = 3
AND CAST("token_attributes"."attributeValue" AS INTEGER) BETWEEN 10 AND 30;

How to get the intersection of 2 mysql queries?

Suppose I have a MySQL table which looks like this:
Each job in the table contains 3 tasks.
How can I get all the JobIds whose taskA is in Done state and taskB is in New state?
In my case, I want a query which returns qwert, and zxcv.
I've come up with this query:
select JobId from MyTable where TaskSeq=0 and TaskState='Done'
intersect
select JobId from MyTable where TaskSeq=1 and TaskState='New';
but my version of MySQL doesn't support the intercept operator.
My ultimate goal is to write the query in sequelize. But I think I should know the MySQL query first so that I can create a sequlize query.
And I also wish that the sequlize query can be done in 1 function instead of multiple functions concatenated with then.
Here's the SQL Fiddle to help you try the table.
You could just use a join:
select mt.JobId
from MyTable mt
join MyTable mt2 on mt2.JobId = mt.JobId
where mt.TaskSeq = 0 and mt.TaskState = 'Done' and mt2.TaskSeq = 1 and mt2.TaskState = 'New'
Here's an attempt at Sequelize on this query, however this is a guess. Hopefully it gives you something to work with:
MyTable.findAll({
attributes: ['JobId', 'TaskSeq', 'TaskState'],
include: [{
model: MyTable,
attributes: ['JobId', 'TaskSeq', 'TaskState'],
where: {
JobId: Sequelize.col('MyTable.JobId'),
TaskSeq: 1,
TaskState: 'New'
}
}],
where {
TaskSeq: 0,
TaskState: 'Done'
}
});

Bookshelf change column data type

I`m using bookshelf.js and I want to change the data type column, this is the example I want to do.
select * from table where date(datetime_col) = '2017-03-14'
the datatime_col is DATETIME and I want to convert to date to execute the query.
this is how I'm trying to do in bookshelf
var Model = new model().query(function (qb) {
qb.where('date(datetime_col)', '=' , date);
}).fetchAll()
this is the error when I´m trying to execute the code above
Error: ER_BAD_FIELD_ERROR: Unknown column 'date(datetime_col)' in 'where clause'
This is a full example how can you use knex.raw and bookshelf for query thanks for answer.
Using between two dates with date time column
var Model = new model().query(function (qb) {
qb.whereBetween( Bookshelf.knex.raw("DATE(colum_datetime)"), [date_var1, date_var2]);
}).fetchAll( { withRelated: ['table1', 'table2', {'table3':function (qb) {
qb.orderBy('date_column', 'desc')
}},'table4'] });
Using where
var Model = new model().query("where", Bookshelf.knex.raw("DATE(colum_datetime)"), "=", date_var).fetchAll( { withRelated: ['table1', 'teble2', {'table3':function (qb) {
qb.orderBy('date_column', 'desc')
}},'table4'] });
It looks like that "bookshelf.js" or the underlying "knex" expect to get an attribute name of your model (like datetime_col), and not a sql-fragment like date(datetime_col).
According to this source, you need to pass a part with the function as "raw" sql.
The proposed solution is to write it like this:
model.query("where", Bookshelf.knex.raw("DATE(field) = ?"), "2017-03-04"))

Firebase timestamp filter

I'm new to firebase, actually I'm trying to load some data based on timestamp and retrieve between two timestamp using startat and endat. Data is pushed through Python.
The data is as shown in the sample screenshot
sample data
The data path popping-fire-7751.firebaseio.com/device488
activevolt: 396
avgPowerFactor: 0.95
avgThdi: 7.5
cubetemp: 37
datetime: "2016-02-08 15:16:32"
timestamp: 1454924792
totalPowerGen: 34
I'm pushing data through python setting the priority as timestamp.
When I try to filter as shown here it returns null. But without startAt and endAt it shows all the values.
http://jsfiddle.net/casperkamal/EZUtP/64/
var startTime = 1454924792;
var endTime = 1454924798;
new Firebase("https://popping-fire-7751.firebaseio.com/")
.startAt(startTime)
.endAt(endTime)
.once('value', show);
can anybody help me on what I'm doing wrong ?
You're trying to skip a level in your JSON tree:
var startTime = 1454924792;
var endTime = 1454924798;
new Firebase("https://popping-fire-7751.firebaseio.com/")
.child('device488')
.startAt(startTime)
.endAt(endTime)
.once('value', show);
I highly recommend that you don't depend on the implicit priority anymore and instead just filter using orderByChild()
new Firebase("https://popping-fire-7751.firebaseio.com/")
.child('device488')
.orderByChild('timestamp')
.startAt(startTime)
.endAt(endTime)
.once('value', show);
You'll need to add an index to your Security Rules:
{
"rules": {
"device488": {
".indexOn": ["timestamp"]
}
}
}
But the more explicit behavior is well worth the effort of adding this.

MongoDB: how to update n records based on ObjectID

I've created a Collection containing 1 million documents, and I'm trying to select 50000 of these records based on the ObjectID, and update one of the values (i'm working in Mongo shell, running on Ubuntu).
Is it possible to define a 50000 document range? It doesn't matter which documents are included in the 50000 range, I simply want to ringfence a definite number of records and run an update operation using the primary id so that I can measure the performance time.
The code I've tried to run doesn't work:
use Assignment
var _start = new Date()
db.FlightsDate.update({$set:{Airtime: 8888}}).limit(50000).hint({_id:1});
var _end = new Date();
print("Time to Bulk Update AirTime key for 50000 documents… " + ((_end _start)/1000));
...i'm gathering that MongoDB needs me to include a query in the command to specify which docs are to be updated (I now understand from reading other posts that .limit won't constrain the number of records than an .update writes to).
Please can anyone advise a method that'll enable me to define the number of records to be updated?
Grateful for advice.
R,
Jon
If you are simply looking for a "range" that covers 50,000 of the documents in the collection then your best approach is to query and find the "starting" and "ending" documents of your range first. Then apply that "range" specification to your update.
var start_id = db.FlightsDate.find({}).limit(1).toArray()[0]._id;
var end_id = db.FlightsDate.find({}).skip(49999).limit(1).toArray()[0]._id;
var _start = new Date();
db.FlightsDate.update(
{ "_id": { "$gte": start_id, "$lte": end_id } },
{ "$set"; { "Airtime": 8888 } },
{ "multi": true }
);
var _end = new Date();
( _end - _start )/1000;
If you then wanted the next 50,000 in an additional range then :
var start_id = db.FlightsDate.find(
{ "_id": { "$gt": end_id } }
).limit(1).toArray()[0]._id;
var end_id = db.FlightsDate.find(
{ "_id": { "$gt": end_id } }
).skip(49999).limit(1).toArray()[0]._id;
And do it all again.
The point is you need to know where to "start" and when to "end" within a range to limit your update to just 50,000 documents without any other criteria to do so.
Also note the usage of "multi" in the update method there. By default, .update() does not "update" any more than one document, essentially being the first match. So what you mean to do is update "all documents in the range" and that is why you need to apply "multi" here.

Categories

Resources