I am trying to query with multiple joins, but what happens is if I add conditions to the where I get the prisma version as response. For example the following query works
const products = await prisma.products.findMany({
where: {
is_enable: true,
is_deleted: false,
},
include: {
items: {
where: {
is_deleted: false
},
include: {
parts: {
include: {
subvehicles: {
include: {
vehicles: {
include: {
manufacturers: true
}
}
}
}
}
}
}
}
},
skip: replacements.offset,
take: replacements.limit,
});
But if I add a condition (the condition does not matter, but if I add the condition the behaviour changes)
const products = await prisma.products.findMany({
where: {
is_enable: true,
is_deleted: false,
},
include: {
items: {
where: {
is_deleted: false
},
include: {
parts: {
where: {
is_deleted: false,
},
include: {
subvehicles: {
include: {
vehicles: {
include: {
manufacturers: true
}
}
}
}
}
}
}
}
},
skip: replacements.offset,
take: replacements.limit,
});
I get
{
"clientVersion": "3.6.0"
}
UPDATE
In the first case the generated query is
prisma:client Prisma Client call: +1s
prisma:client prisma.products.findMany({
prisma:client where: {
prisma:client is_enable: true,
prisma:client is_deleted: false
prisma:client },
prisma:client include: {
prisma:client items: {
prisma:client where: {
prisma:client is_deleted: false
prisma:client },
prisma:client include: {
prisma:client parts: {
prisma:client include: {
prisma:client subvehicles: {
prisma:client include: {
prisma:client vehicles: {
prisma:client include: {
prisma:client manufacturers: true
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }) +1ms
prisma:client Generated request: +1ms
prisma:client query {
prisma:client findManyproducts(where: {
prisma:client is_enable: true
prisma:client is_deleted: false
prisma:client }) {
prisma:client id
prisma:client code
prisma:client description
prisma:client position
prisma:client is_enable
prisma:client category
prisma:client filename
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client items(where: {
prisma:client is_deleted: false
prisma:client }) {
prisma:client id
prisma:client part_id
prisma:client product_id
prisma:client quantity
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client parts {
prisma:client id
prisma:client subvehicle_id
prisma:client oem
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client subvehicles {
prisma:client id
prisma:client vehicle_id
prisma:client submodel
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client vehicles {
prisma:client id
prisma:client manufacturer_id
prisma:client model
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client manufacturers {
prisma:client id
prisma:client name
prisma:client position
prisma:client is_deleted
prisma:client creation_date
prisma:client last_modification_date
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client }
prisma:client +0ms
In the second case
prisma:client clientVersion: 3.6.0 +0ms
prisma:client clientEngineType: library +0ms
Related
I'm trying to realize the query, where I can find all records, which at least one of the attributes includes the text, user send with request, for that I use where, but it can search, as I understand, in only own model, but i need it to search it in parent model and in associated filds together, not apart.
There is my models:
const Picture = sequelize.define<IPictureInstance>('picture', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
img: { type: DataTypes.STRING, allowNull: false },
mainTitle: { type: DataTypes.STRING, allowNull: false },
description: { type: DataTypes.TEXT }
});
const PictureInfo = sequelize.define<IPictureInfoInstance>('pictureInfo', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
title: { type: DataTypes.STRING, allowNull: false },
description: { type: DataTypes.STRING, allowNull: false }
});
const PictureTag = sequelize.define<IPictureTagInstance>('pictureTag', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
text: { type: DataTypes.TEXT, allowNull: false }
});
const PicturesTags = sequelize.define<IPicturesTagsInstance>('picturesTags', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }
});
And their associations:
Picture.belongsToMany(PictureTag, { through: PicturesTags, as: "tags", onDelete: 'cascade' });
PictureTag.belongsToMany(Picture, { through: PicturesTags, as: "pictures", onDelete: 'cascade'
});
Picture.hasMany(PictureInfo, { onDelete: "cascade" });
PictureInfo.belongsTo(Picture);
That's what I tried to do:
static async getPictures(query: string | undefined) {
const pictures = await models.Picture.findAll({
where: {
[Op.or]: {
mainTitle: { [Op.iRegexp]: `${query}` },
description: { [Op.iRegexp]: `${query}` },
},
},
include: [
{
model: models.PictureInfo,
as: "pictureInfos",
where: {
[Op.or]: {
title: { [Op.iRegexp]: `${query}` },
description: { [Op.iRegexp]: `${query}` }
}
},
required: false
},
{
model: models.PictureTag,
as: "tags",
attributes: ["id", "text"],
where: { text: { [Op.iRegexp]: `${query}` } },
through: {
attributes: [],
},
required: false
}
],
});
return pictures;
}
But in this case, when it can't find records in first where param it returns an empty array, I understand it, but it isn't a behavior I need.
I need to check every attribute together.
So, if user send query=cat, it will check mainTitle and description, if there is nothing, it will check associated pictureInfos fields and after, if there is nothing, check pictureTags associated fields, that's what I need, will be grateful for the help.
My solution:
static async getPictures(query: string | undefined) {
const whereStatement = {
[Op.or]: {
mainTitle: { [Op.iRegexp]: `${query}` },
description: { [Op.iRegexp]: `${query}` },
"$tags.text$": { [Op.iRegexp]: `${query}` },
"$pictureInfos.title$": { [Op.iRegexp]: `${query}` },
"$pictureInfos.description$": { [Op.iRegexp]: `${query}` },
}
};
const pictures = await models.Picture.findAll({
where: whereStatement,
include: [
{
model: models.PictureInfo,
as: "pictureInfos",
},
{
model: models.PictureTag,
as: "tags",
}
],
});
return pictures;
}
But I'm still confused with those $ symbols, what they are for, I couldn't find the answer in documentation?
Link to the Sequelize documentation, to confirm my answer
I use those filters on my user controller and they works just fine. But now the system needs to apply some of those filters only when the user is not an super user. how can i use the filter property to check if the user is a su? Here is the actual code:
#Crud({
model: {
type: User,
},
routes: {
createOneBase: {
returnShallow: true
},
updateOneBase: {
returnShallow: true,
},
replaceOneBase: {
returnShallow: true,
},
exclude: ['deleteOneBase', 'updateOneBase', 'createManyBase'],
},
params: {
id: {
field: 'id',
type: 'number',
primary: true,
},
},
query: {
join: {
createdBy: { eager: true, exclude: ['password'] },
updatedBy: { eager: true, exclude: ['password'] },
members: { eager: true, alias: 'groups' },
contacts: {eager: true, alias: 'contacts'},
'members.group': { eager: true },
userCompanies: { eager: true },
'userCompanies.companyId': { eager: true }
},
filter: {
exclude: {
$eq: false,
},
'contacts.exclude': {
$eq: false,
},
'userCompanies.exclude': {
$eq: false,
}
},
sort: [
{
field: 'id',
order: 'ASC',
}
]
}
})
The only one which will be applied no matter the user type is the exclude one.
I've solved by myself using the override method with ParsedRequest.
#Override('getManyBase')
async getMany(#ParsedRequest() req: CrudRequest, #UserReq() user: User) {
if(!user.su) {
req.parsed.filter.push({
field: 'contacts.exclude',
operator: '$eq',
value: false
},
{
field: 'userCompanies.exclude',
operator: '$eq',
value: false
})
}
return await this.service.getMany(req);
}
I have 2 models that I am associating like this. Customer is associated to application by 1:M relationship.
customer:
'use strict';
module.exports = (sequelize, DataTypes) => {
let customer = sequelize.define('customer', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING
},
account_id: {
type: DataTypes.STRING
},
code: {
type: DataTypes.STRING
},
createdAt: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
}
},
{
underscored: true,
freezeTableName: true,
tableName: 'customer'
});
customer.associate = function(models) {
// associations can be defined here
customer.hasMany(models.application, { foreignKey:
'customer_id' });
};
sequelize.sync()
.then(() => customer.create(
{ name: "customer1", account_id: "cust-1-acct-1", code: "ACME Inc." }
)).then(function(customer) {
console.log('customers created');
}).then(() => customer.create(
{ name: "customer2", account_id: "cust-2-acct-2", code: "test Cust" }
)).then(function(customer) {
console.log('customers created');
})
.catch(function(err) {
console.log(err);
});
return customer;
}
application:
'use strict';
module.exports = (sequelize, DataTypes) => {
let application = sequelize.define('application', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
sortable: true
},
creation_date: {
type: DataTypes.NUMERIC,
sortable: true
},
customer_id: {
type: DataTypes.INTEGER
},
createdAt: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
}
},
{
underscored: true,
freezeTableName: true,
tableName: 'application'
});
application.associate = function(models) {
// associations can be defined here
application.belongsTo(models.customerView, { through: 'customer_id' });
};
sequelize.sync()
.then(() => application.create(
{ customer_id: "1", name: "application 1", creation_date: "1556724178700" }
)).then(() => application.create(
{ customer_id: "1", name: "application 2", creation_date: "1556724178700" }
)).then(() => application.create(
{ customer_id: "2", name: "application 3", creation_date: "1556724178700" }
))
.then(function(application) {
console.log('applications created');
})
.catch(function(err) {
console.log(err);
});
return application;
}
These 2 tables are getting created as expected, but without the foreign key constraint that I am expecting. The foreign key should be on the application table, on customer_id.
What am I doing wrong?
I would like to query ManufacturerId: manufacturer_id only if manufacturer_id is not equal to null.
I tried this code but its giving me syntax error:
/* Get Brands List */
router.get('/', function(req, res) {
var archived_status = req.query["archived-status"];
var manufacturer_id = req.params.manufacturer_id;
models.Brand.findAll({
where: {
brand_archived_status: archived_status,
if(manufacturer_id != null){
ManufacturerId: manufacturer_id
}
},
include: [{
model: models.Job,
required: false
}]
}).
then(function(brands) {
res.status(200).json(brands);
}, function(error) {
res.status(500).send(error);
});
});
Why don't you just make whole where condition outside of Sequelize query , Here you go :
let where = {
brand_archived_status: archived_status
};
if (manufacturer_id != null) {
where['ManufacturerId'] = manufacturer_id
}
models.Brand.findAll({
where,
include: [{
model: models.Job,
required: false
}]
})
This wil look clean and simple :)
This is how my models are structured in sails:
myapp
--api
----controllers
----models
-----User.js
------Role.js
User.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {foreignKey: 'id', as: 'role' });
}
};
Role.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
}
}
};
After sails lift, in the postgresql I have users table with id, username, password, createdat and updatedat + roles table with id, name, createdat and updatedat. No foreignKey for Roles in Users table.
How I can fix this?
I'm using sails-hook-sequelize and sails-hook-sequelize-blueprints, can this occur because of them?
Thanks!
Edit:
The correct way was:
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {
as : 'role',
foreignKey: {
name: 'roleId',
allowNull: false
}
});
}
};
The createdAt and updatedAt columns are added by default unless you set the timestamps option to false. See the docs.
To add foreign key constraints, you need to define associations for the Roles model.