Sequilize association for 2 foriegn key of same model - mysql

I need to execute below query using sequelize
SELECT * FROM haulerrfquotes
LEFT JOIN quotes ON quotes.jobId = haulerrfquotes.jobId AND haulerrfquotes.haulerId = quotes.haulerId
WHERE haulerrfquotes.jobId = '11'
But i am not getting how to use two foriegn keys in same model(haulerrfquotes) and to create association of both foriegn keys to single model (quotes)

In sequelize, you could define your own join condition by supplying the on options in the include object. Here's an example to perform the query in question
haulerrfquotes.findAll({
where: {
jobId: 11
},
include: [{
model: quotes,
required: false,
on: {
jobId: {
$col: 'haulerrfquotes.jobId'
},
haulerId: {
$col: 'haulerrfquotes.haulerId'
}
}
}]
}).then(result => {
// The rest of your logic here...
});

Related

Query model based on value inside one of its columns

I have a sequelize model called staff. One of the staff columns is called locations which holds the id's of all the locations this staff is available at. I want to create a query that uses a Location ID to get all staff active at that location. How can I do that using the ORM?
Assuming I have understood your question correctly and your locations column contains CSV data, then you need to use FIND_IN_SET() -
Staff.findAll({
where: sequelize.where(sequelize.fn('FIND_IN_SET', locationId, sequelize.col('locations')), {[Op.gt]: 0})
})
A better option would be to normalize your data as this query is non-SARGable.
In Sequelize, you can perform a query to filter staff based on their locations using the include and where options in your query.
const staff = await Staff.findAll({
include: [
{
model: Location,
as: 'locations',
where: { id: locationId },
through: { attributes: [] }
}
]
});
const findStaff = await StaffModel.findAll({
where: {
locationId: "your locationId"
}
})

Convert SQL query to sequelize query with multiple tables

I've been at this for several days attempting to convert what I thought was a relatively simple SQL query into sequelize format. I cannot seem to figure it out for the life of me. I'm relatively new to sequelize, and my SQL skills can use some help as well.
Any help is greatly appreciated, thanks!
Here is the SQL query I have (which works for what I'm attempting to do) which I'm struggling to get to work in sequelize:
SELECT
book.id,
book.author,
book.title,
book_type.type,
book_sub_type.sub_type,
book_location.location,
book_language.language
FROM book
INNER JOIN book_type ON book.book_type_id = book_type.id
INNER JOIN book_sub_type ON book.book_sub_type_id = book_sub_type.id
INNER JOIN book_location ON book.book_location_id = book_location.id
INNER JOIN book_language ON book.book_language_id = book_language.id
WHERE
book.author LIKE '%history%' OR
book.title LIKE '%history%' OR
book_type.type LIKE '%history%' OR
book_sub_type.sub_type LIKE '%history%' OR
book_language.language LIKE '%history%' OR
book_location.location LIKE '%history%'
ORDER BY book_type.type, book_sub_type.sub_type;
Here is as far as I have gotten (this sequelize query returns 0 results because it is searching for the substring "history" in all columns, instead of at least one column):
const books = await Book.findAll({
where: {
[Op.or]: [
{author: { [Op.substring]: 'history' }},
{title: { [Op.substring]: 'history' }}
]
},
attributes: ['id', 'author', 'title'],
include: [
{
model: BookType,
attributes: ['type'],
where: {
type: { [Op.substring]: 'history' }
}
},
{
model: BookSubType,
attributes: ['sub_type'],
where: {
sub_type: { [Op.substring]: 'history' }
}
},
{
model: BookLanguage,
attributes: ['language'],
where: {
language: { [Op.substring]: 'history' }
}
},
{
model: BookLocation,
attributes: ['location'],
where: {
location: { [Op.substring]: 'history' }
}
},
]
});
My schema is as follows:
`book` table columns:
`id`, `author`, `title`, `book_type_id`, `book_sub_type_id`,
`book_language_id`, `book_location_id`
`book_type` table columns:
`id`, `type`
`book_sub_type` table columns:
`id`, `sub_type`
`book_location` table columns:
`id`, `location`
`book_language` table columns:
`id`, `language`
In sequelize, I have the following relationships established:
Book.belongsTo(BookType);
Book.belongsTo(BookSubType);
Book.belongsTo(BookLanguage);
Book.belongsTo(BookLocation);
BookType.hasMany(Book);
BookSubType.hasMany(Book);
BookLanguage.hasMany(Book);
BookLocation.hasMany(Book);
The output should be 7 columns:
book.id, book.author, book.title, book_type.type, book_sub_type.sub_type, book_location.location, book_language.language
Sequelize build a SQL with a conditions in JOINs, so this is not good aproach. You should remove all where conditions from includes. There was a way in a sequelize <4.0.0 to write conditions to subquery using syntax
where: {
$or: [{
'$book.sub_type$$': 'history'
}, {
'$book_type.type$': 'history'
}]
}
but I think this is not longer supported. Only way would be a custom query or use a sequelize literal in where object.
where: {
[Op.or]: [{
Sequelize.literal(`book_type.type LIKE ${history}`)
}, {
Sequelize.literal(`book_sub_type.sub_type LIKE ${history}`)
}]
}
Keep in mind that with this approach there is a risk of SQL injection so you should validate an input or use some escape character strategy. Check sequelize raw queries and seqeulize literal

MySQL foreign key name, what is it?

I am using Sequelize, a nodejs ORM for mysql. Using mysql workbench I made an EEM diagram and pushed that design into the db, so far so good.
Now in Sequelize I have to tell it what the design of the DB looks like, part of that is telling it what foreign keys are called.
In Workbench there is a foreign key tab in the tablethere are variables formatted likefd_positions_tradingPLan1` but I never name that, in fact in my EEM diagram I have
Then if I go to that foreign keys tab at the bottom I get this. I am confused as to exactly what I should tell the ORM the foreign key is...
Let's take your positions Table as reference. To build your model on sequelize you have to do the following:
module.exports = (sequelize, DataTypes) => {
const Position = sequelize.define('Position', { // this is the name that you'll use on sequelize methods, not what you have on your db
// define your columns like this:
tradeName: { //the name of the variable that you'll use on sequelize and js
field: 'trade_name', //the actual name of your column on the table
type: DataTypes.STRING(128) // the data type
},
// .......
// for your foreignKeys you have to define the column like your other attributes.
userId: {
field: 'user_id',
type: DataTypes.INTEGER
},
}, {
tableName: 'positions', //this is the name of your table on the database
underscored: true, // to recognize the underscore names
createdAt: 'created_at', //
updatedAt: 'updated_at',
});
//now for your association let's say that you defined your USER table like this example.
Position.associate = (models) => {
// on the foreignKey value, youhave to put the same that you define above, and on the db.
Position.belongsTo(models.User, { as: 'User', foreignKey: 'user_id' });
//depending on your other relations, you are gonna use hasMany, hasOne, belongsToMany
};
return Position;
};
Sequelize does the association only one way, that means that on this example, you can't query with sequelize from User to Position, to be able to
have two way association you have to defined on both models.
User.associate = (models) => {
// on this case we use hasMany cause user can have many positions I suppose, if not, use hasOne
User.hasMany(models.Poisition, { as: 'positions', foreignKey: 'user_id' }); //remeber to use the same foreignKey name
};
UPDATE:
as is an identfier for Sequelize. Let's say you make two associations for the same model, later when you try to query one of this associations, you can specify the association that you want
User.associate = (models) => {
User.hasMany(models.Poisition, { as: 'positions', foreignKey: 'user_id' });
User.hasMany(models.Poisition, { as: 'customerPositions', foreignKey: 'customer_id' });
};
//the actual association call
User.findAll({
include:[{
model: db.user,
as: 'positions'
}, {
model: db.user,
as: 'customerPositions'
}]
})
Now for fk_positions_users1, this is an identifier for MySQL itself. Sequelize only check for the foreignKey and the models involve. Obviously when Sequelize create the reference, it gives a template name using the table and column name. I tried myself creating a new foreignKey on my table and then updating the model and everything goes fine. You should'nt have problems with that.

Make a join query in loopback.io

I am trying to build a simple application using loopback.io as process of my learning. I have set up the project, created models and apis are working fine.
Now I am trying to create a custom api which can get the data from two different models by making a join query. So i have a two models
stories : id, title, noteId
notes : id , desc
i have stories.js file as
module.exports = function(Stories) {
Stories.list = function(cb) {
// make a join query
};
Stories.remoteMethod(
'list', {
http: {
path: '/list',
verb: 'get'
},
returns: {
arg: 'list',
type: 'array'
}
}
);
};
In general i will make a join in php api but here i am bit confused.Can i pass a raw query to database here or does loopback has some different way of achieving this. Any help would be appreciated.
You don't need to pass sql query. You can query data using PersistedModel find method by using include filter
In order to use include filter you have to create model relation.
For example:
Note relation:
"relations": {
"stories": {
"type": "hasMany",
"model": "Story",
"foreignKey": "noteId"
}
},
Query:
Note.find({include: ['stories']}, function(err, data) { ... });

How to query a dynamodb2 index using boto?

How can I query a dynamodb2 table with an index using boto? I'm not able to piece together enough information from the documentation or unit tests for boto.
I have a local index created as:
fields.KeysOnlyIndex('NameIndex', parts=[
fields.HashKey('account_id', data_type='S'),
fields.RangeKey('name', data_type='S'),
])
And would like to lookup an item using the account_id and name.
Attempting to make the call table.query( account_id__eq=account['id'], name__eq = name ) results in the error Query condition missed key schema element id.
Note: I would also prefer to avoid using the Table class and work directly with the connection.
with Table:
table = Table('accounts')
results = table.query(index='NameIndex', account_id__eq=account['id'], name__eq=name)
or with Connection:
results = conn.query(
table_name='accounts',
index_name='NameIndex',
select='ALL_PROJECTED_ATTRIBUTES',
key_conditions={
'account_id': {
'AttributeValueList': [
{'S': account['id']},
],
'ComparisonOperator': 'EQ',
},
'name': {
'AttributeValueList': [
{'S': name},
],
'ComparisonOperator': 'EQ',
},
}
)