How do I write this Raw Postgres query in sequelize - sql

I Have this postgres RAW query, I wanted to write it in Sequelize. How do I do this since I have less idea about Writing queries having JOINS in Sequelize. I have made models and Associations.
These are models and associations.
TestParticipant.hasMany(ParticipantHistory, {
sourceKey: "id",
foreignKey: "participantId",
as: "paticipantStatuses"
})
ParticipantHistory.belongsTo(TestParticipant, {
foreignKey: "participantId",
as: "paticipantStatuses"
})
This is the raw Query I wanna transform into Sequelize query
SELECT participant_histories.participant_id,
participant_histories.created_at,participant_histories.previous_status,
participant_histories.status,test_participants.test_type_id,test_participants.id,
test_participants.email,test_participants.scheduled_at,test_participants.valid_till,
test_participants.is_proctored
FROM test_participants
INNER JOIN participant_histories ON test_participants.id=participant_histories.participant_id
WHERE user_id='${userId}'
AND participant_histories.status='${activity}'
AND participant_histories.created_at>='${isoDate}'

Because I don't see model definitions in the post I suggest only something like this:
// First of all you should correct an alias for TestParticipant like this
ParticipantHistory.belongsTo(TestParticipant, {
foreignKey: "participantId",
as: "paticipant"
})
const rows = await ParticipantHistory.findAll({
raw: true,
attributes: ['participant_id', 'created_at', 'previous_status', 'status'],
where: {
status: activity,
created_at: {
[Op.gte]: isoDate
}
},
include: [{
required: true // this turns into INNER JOIN
model: TestParticipant,
attributes: ['test_type_id', 'id', 'email', 'scheduled_at', 'valid_till', 'is_proctored'],
as: 'participant',
where: {
user_id: userId
}
}]
})

Related

SQL query to PostgeSQL tables [duplicate]

This question already has answers here:
PostgreSQL "Column does not exist" but it actually does
(6 answers)
sql statement error: "column .. does not exist"
(1 answer)
Postgresql Column Not Found, But Shows in Describe
(1 answer)
Closed 2 years ago.
I have a problem.
SELECT *
FROM posts CROSS JOIN public."postReactions" AS reactions
WHERE posts.userId = '423abb9e-a00d-4045-9e88-4a85897f67e4'
But the response from DB is like 'ERROR: column posts.userid doesn't exist.
LINE 3: WHERE posts.userId = '423abb9e-a00d-4045-9e88-4a85897f67e4'.
Result of CROSS JOIN below:
Posts table
PostReactions table
Sequelize models below:
export default models => {
const {
User,
Post,
PostReaction,
PostNegativeReaction,
Comment,
Image
} = models;
User.hasMany(Post);
User.hasMany(PostReaction);
Post.belongsTo(User);
Post.hasMany(PostReaction);
PostReaction.belongsTo(Post);
PostReaction.belongsTo(User);
};
This is my associations:
export default {
up: (queryInterface, Sequelize) => queryInterface.sequelize
.transaction(transaction => Promise.all([
queryInterface.addColumn('posts', 'userId', {
type: Sequelize.UUID,
references: {
model: 'users',
key: 'id'
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL'
}, { transaction }),
queryInterface.addColumn('postReactions', 'userId', {
type: Sequelize.UUID,
references: {
model: 'users',
key: 'id'
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL'
}, { transaction }),
queryInterface.addColumn('postReactions', 'postId', {
type: Sequelize.UUID,
references: {
model: 'posts',
key: 'id'
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL'
}, { transaction }),
])),
down: queryInterface => queryInterface.sequelize
.transaction(transaction => Promise.all([
queryInterface.removeColumn('posts', 'userId', { transaction }),
queryInterface.removeColumn('postReactions', 'userId', { transaction }),
queryInterface.removeColumn('postReactions', 'postId', { transaction })
]))
};
MERN stack.
Main problem: how to do a request to db that will receive the response with POSTS body (only liked by the current user).
This would be possible if the table were created using escaped column names . . . "postId" rather than postId.
I suspect that is the problem. The best solution is to recreate the table and not escape any identifiers, ever. Alternatively, you can use the escaped column name.

Typeorm - Find entries by ManyToMany relation

I am using Nestjs with Typeorm and Mysql, and I can't figure out a good way to filter entries by their many to many relation.
I have these 2 entities:
Group Entity:
#Entity({ name: 'groups' })
export class Group {
#ManyToMany(() => Tag, { eager: true })
#JoinTable()
tags: Tag[];
}
Tag Entity
#Entity({ name: 'tags' })
export class Tag {
#Column()
#Index({ unique: true })
tag?: string;
}
And would like to search all groups that have a tag with a specific text.
ie. all groups that have the tag.tag "sport"
Tried this code:
const args = {
where: [
{
'tags': In([Like(`%sport%`)]),
}
],
relations: ['tags'], // TAGS
take: filter.take,
skip: filter.skip,
order: filter.order
};
return super.findAll(args);
but it doesn't seem to work..
any help would be great!
return find({
where: {
tags: {
tag: Like(`%sport%`),
},
},
relations: ['tags'],
});
Almost, typeorm accepts an ObjectLiteral or keyof typeof Tags from relations like so:
FindConditions<T>: {
where: {
[s: keyof typeof T]: any,
},
}
That's not quite it but that's the general gist. And if the keyof T is a relation then any is replaced with keyof relation pretty much anyway.
This is the full type for findConditions https://github.com/typeorm/typeorm/blob/master/src/find-options/FindConditions.ts

WhereHas method in Sequelize

Sequelize reminds me Eloquent library in Laravel, but I can't find anything similar to method WhereHas that allows filtering records using associated tables.
Say, I need to select all users in the group with ID = 1, then I can use the query below, but then I have to extract users from results.
let group = group.findOne({
include: [{
as: 'users',
model: schema.users
}],
where: {
id: groupId
}
})
let users = group.users;
Is there a method like WhereHas that I could use to create a query for users only and then filter them using association with groups?
let users = group.findAll({
whereHas: [{
as: 'groups',
model: schema.groups,
where: {
id: groupId // something like this, group is used for filtering only
}
}]
})
I had the same problem and my solution is required:true in include option. If you want to find all users that join a group, you can use code below:
let users = users.findAll({
include: [{
as: 'groups',
model: schema.groups,
required:true,
where: {
id: groupId
}
}],
})

Sequelize and Graphql reverse lookup

I have two Models:
River.associate = models => {
River.hasMany(models.Fish, { as: 'Fishes' });
};
Fish.associate = models => {
Fish.belongsTo(models.River);
};
type River {
id: ID!
name: String!
alternative: String!
geojson: JSON
fishes: [Fish]
}
type Fish {
id: ID!
name: String!
}
How would I findAll Rivers given a list of Fish ID's? Im not sure how the query must look for this for graphql and sequelize?
type Query {
river(id: ID!): River
**rivers(fishIds: ARRAY): River ??????**
fishes: [Fish]
}
Query: {
rivers: (_, { fishIds }) => {
return River.findAll({
where: {
fishes: fishIds
}
});
},
}
You can specify WHERE clauses for each of the models you include. Moreover, doing so will convert the eager load to an inner join (which is what you want), unless you explicitly set the required param to false.
That means you should be able to do something like:
River.findAll({ include:
[
{
model: Fish,
where: { id: fishIds }
},
],
})

Sequelize 'where' condition starts with 'AND' instead of 'WHERE'

This doesn't make sence. Sequelize creates a where condition which starts with an AND instead of a WHERE.
I'm trying to execute this query:
var query = {
limit: 10,
order: [
['id', 'DESC']
],
//attributes: ['id', 'name', 'supplier_id', 'created_at', 'url'],
include: [
{
required: false,
model: models.termTaxonomies,
include: [{
model: models.term
}, {
attributes: ['id'],
model: models.taxonomy
}],
where: ["termRelationships.product_id IS NULL"],
},
models.image,
models.supplier
],
};
Which creates below SQL after executing above query with Product.findAll(query).
SELECT "product".*
,"termTaxonomies"."id" AS "termTaxonomies.id"
,"termTaxonomies"."taxonomy_id" AS "termTaxonomies.taxonomy_id"
,"termTaxonomies"."term_id" AS "termTaxonomies.term_id"
,"termTaxonomies"."parentId" AS "termTaxonomies.parentId"
,"termTaxonomies"."hierarchyLevel" AS "termTaxonomies.hierarchyLevel"
,"termTaxonomies"."distance" AS "termTaxonomies.distance"
,"termTaxonomies.termRelationships"."product_id" AS "termTaxonomies.termRelationships.product_id"
,"termTaxonomies.termRelationships"."term_taxonomy_id" AS "termTaxonomies.termRelationships.term_taxonomy_id"
,"termTaxonomies.term"."id" AS "termTaxonomies.term.id"
,"termTaxonomies.term"."name" AS "termTaxonomies.term.name"
,"termTaxonomies.term"."plural" AS "termTaxonomies.term.plural"
,"termTaxonomies.term"."sin_article" AS "termTaxonomies.term.sin_article"
,"termTaxonomies.term"."plu_article" AS "termTaxonomies.term.plu_article"
,"termTaxonomies.taxonomy"."id" AS "termTaxonomies.taxonomy.id"
,"images"."id" AS "images.id"
,"images"."deal_id" AS "images.deal_id"
,"images"."image" AS "images.image"
,"supplier"."id" AS "supplier.id"
,"supplier"."name" AS "supplier.name"
,"supplier"."url" AS "supplier.url"
,"supplier"."logo" AS "supplier.logo"
,"supplier"."clicks" AS "supplier.clicks"
,"supplier"."order" AS "supplier.order"
FROM (
SELECT "product"."id"
,"product"."name"
,"product"."subtitle"
,"product"."url"
,"product"."prod_specs"
,"product"."prod_desc"
,"product"."supplier_id"
,"product"."created_at"
,"product"."updated_at"
,"product"."active"
FROM "products" AS "product"
ORDER BY "product"."id" DESC LIMIT 10
) AS "product"
LEFT JOIN (
"term_relationships" AS "termTaxonomies.termRelationships" LEFT JOIN "term_taxonomies" AS "termTaxonomies" ON "termTaxonomies"."id" = "termTaxonomies.termRelationships"."term_taxonomy_id"
) ON "product"."id" = "termTaxonomies.termRelationships"."product_id"
AND termRelationships.product_id IS NULL
LEFT JOIN "terms" AS "termTaxonomies.term" ON "termTaxonomies"."term_id" = "termTaxonomies.term"."id"
LEFT JOIN "taxonomies" AS "termTaxonomies.taxonomy" ON "termTaxonomies"."taxonomy_id" = "termTaxonomies.taxonomy"."id"
LEFT JOIN "images" AS "images" ON "product"."id" = "images"."deal_id"
LEFT JOIN "suppliers" AS "supplier" ON "product"."supplier_id" = "supplier"."id"
ORDER BY "product"."id" DESC;
Check 6th last row (AND termRelationships.product_id IS NULL).
The tables for this case:
I'm trying to get all Products with their suppliers and offers, which aren't categorized yet (so which are not inside termTaxonomies for now).
It's easy to do this with a sql query, but now we are using an ORM (Sequelize), we would love to just use it completely. Anyone who can help us out?
Guess it's a bit too much to post all of my models below so I'll try to keep is short:
associations product model:
product.hasMany(_models.offer, {
foreignKey: 'product_id'
});
product.belongsToMany(_models.termTaxonomies, {
through: _models.termRelationships,
foreignKey: 'product_id'
});
product.hasMany(_models.image, {
foreignKey: 'deal_id'
});
product.belongsTo(_models.supplier, {
foreignKey: 'supplier_id'
});
associations offer model:
offer.belongsTo(_models.product, {
foreignKey: 'product_id'
});
offer.hasMany(_models.sentDeals, {
foreignKey: 'offer_id'
});
offer.hasMany(_models.transaction, {
foreignKey: 'offer_id'
});
associations supplier model:
supplier.hasMany(_models.product, {
foreignKey: 'supplier_id'
});
supplier.hasMany(_models.scraperLog, {
foreignKey: 'scraper_id'
});
associations termTaxonomies model:
termTaxonomies.belongsToMany(_models.product, {
through: _models.termRelationships,
foreignKey: 'term_taxonomy_id',
});
termTaxonomies.belongsTo(_models.term, {
foreignKey: 'term_id',
});
termTaxonomies.belongsTo(_models.taxonomy, {
foreignKey: 'taxonomy_id',
});
The and is the continuation of the LEFT JOIN:-
LEFT JOIN (
"term_relationships" AS "termTaxonomies.termRelationships" LEFT JOIN "term_taxonomies" AS "termTaxonomies" ON "termTaxonomies"."id" = "termTaxonomies.termRelationships"."term_taxonomy_id"
) ON "product"."id" = "termTaxonomies.termRelationships"."product_id"
AND termRelationships.product_id IS NULL