I have the following models defined:
var Order = sequalize.define(
"order",
{
id: {
type: Sequelize.STRING,
primaryKey: true,
},
menuId: {
type: Sequelize.UUID,
field: "menu_id",
},
},
{
timestamps: false,
}
);
Item.belongsToMany(Order, { through: OrderItem });
Order.belongsToMany(Item, { through: OrderItem });
and
var OrderItem = sequalize.define(
"order_item",
{
orderId: {
type: Sequelize.UUID,
field: "order_id",
},
itemId: {
type: Sequelize.UUID,
field: "item_id",
},
count: {
type: Sequelize.INTEGER,
field: "count",
},
},
{
timestamps: false,
freezeTableName: true,
}
);
I am trying to figure out how to add a order with items without creating items but just adding them to the relationship.
I have this initial format for the order:
{
"id": "som-other-id7",
"items": [{"id": "727f9b52-a88b-4ec3-a68c-98d190564497", "count": 2}, {"id": "7dfd30e7-2d4a-4b16-ae3d-20a330d9b438"}],
"menuId": "7715af03-968f-40e5-9eb2-98016f3deeca"
}
and I try to add it to the db in the following way:
Order.create(orderJson)
.then((order) =>
orderJson.items.map((item) => order.addItem(item.id, { count: item.count }))
)
However the count is not populated. I tried:
using setItem instead of addItem
instead of passing item.id passing {itemId, orderId}
You should call addItem like this:
order.addItem(item.id, { through: { count: item.count }})
See an example in BelongsToMany section
Related
Maybe this is a simple fix, but I can't seem to figure out what I'm doing wrong here.
I have a table that lists all the states
Model:
static get jsonSchema() {
return {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string', minLength: 1, maxLength: 100 },
},
}
}
static get relationMappings() {
return {
users: {
relation: Model.HasManyRelation,
modelClass: User,
join: {
from: `${tableNames.state}.id`,
to: `${tableNames.user}.state_id`,
},
},
}
Migration:
await knex.schema.createTable(tableNames.state, (table) => {
table.increments().primary().notNullable()
table.string('name', 100).notNullable()
User table model:
static get jsonSchema() {
return {
type: 'object',
properties: {
id: { type: 'integer' },
first_name: { type: 'string', minLength: 1, maxLength: 100 },
last_name: { type: 'string', minLength: 1, maxLength: 100 },
state_id: { type: 'integer', default: null },
},
}
}
static get relationMappings() {
return {
state: {
relation: Model.BelongsToOneRelation,
modelClass: State,
join: {
from: `${tableNames.user}.state_id`,
to: `${tableNames.state}.id`,
},
}
}
}
User table migration:
await knex.schema
.createTable(tableNames.user, (table) => {
table.increments().primary().notNullable()
table.string('first_name', 100).notNullable()
table.string('last_name', 100).notNullable()
table.integer('state_id').unsigned()
table
.foreign('state_id')
.references('id')
.inTable(tableNames.state)
.onDelete('SET NULL')
})
Now the issue: I want the state_id column to be nullable, as in not every user will have a state assigned to them. But when I try inserting a user with no state_id, I get this: insert or update on table \"user\" violates foreign key constraint \"user_state_id_foreign\".
two things you are doing wrong
in your json schema define your column as state_id: {type: ['integer', 'null']}
in your user migrations make table.integer('state_id').unsigned().nullable()
I have problem to find and filter data from hasMany associations fields, am using following packages version:
"sequelize": "^6.9.0",
"mysql2": "^2.3.3-rc.0"
This is my tables:
const RequestForm = sequelize.define('RequestForm', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false,
noUpdate : true
},
type: DataTypes.STRING
})
const RequestStatus = sequelize.define('RequestStatus', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false,
noUpdate : true
},
})
const Employee = sequelize.define('Employee', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false,
noUpdate : true
}})
This is associations:
RequestStatus.belongsTo(RequestForm);
RequestForm.hasMany(RequestStatus);
RequestStatus.belongsTo(Employee);
Employee.hasMany(RequestStatus);
I am trying to find RequestForm data that have one of following condition:
RequestForm type = "One"
RequestForm type = "Two"
one of RequestStatus EmployeeId(FK) equal to "123e4567-e89b-12d3-a456-426614174000"
and i want return all RequestStatus of RequestForm, so i can't but where in include
This My code but not working and get error -> original: Error: Unknown column 'RequestStatus.EmployeeId' in 'where clause'
RequestForm.find({
where: {
[Op.or]: [
{type: {[Op.in]: ["One", "Two"]}},
{
employee_id_value: Sequelize.where(
Sequelize.col("RequestStatuses.EmployeeId"),
{
[Op.eq]: "123e4567-e89b-12d3-a456-426614174000",
}
)
},
]
},
include:[
{
model: RequestStatus,
attributes: ['id', 'EmployeeId'],
required: false,
},
{Other Models}
]
})
You misspelled RequestStatus in Sequelize.col and you don't need to indicate employee_id_value field, use Sequelize.where directly:
where: {
[Op.or]: [
{
type: {
[Op.in]: ["One", "Two"]
}
},
Sequelize.where(Sequelize.col("RequestStatus.EmployeeId"),
Op.eq, "123e4567-e89b-12d3-a456-426614174000")
]
},
I am new to Sequelize ORM so I am struggling to get through it.
I want to get a list of items and count of associated items by applying filter.
Here are my models
const ActionModel = db.define(
'action',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
...
buttonIndex: { type: Sequelize.INTEGER },
...
},
{
tableName: 'action',
},
)
const PageModel = db.define(
'pages',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
pageTitle: { type: Sequelize.INTEGER },
pageLink: { type: Sequelize.STRING },
},
{
tableName: 'pages',
},
)
PageModel.hasMany(Action, { as: 'actions', onDelete: 'CASCADE'})
So If I get a list of pages, it will look like this
[
{
"id": 1,
"pageTitle": "Python community",
"pageLink": "https://fairy-dev.io/python",
}
]
The actions are associated with pages as they happen on the pages.
I want to add two more fields to the response.
visitCount and buttonClickCount
visitCount is total number of actions on the page where buttonIndex == 0
buttonClickCount is total number of actions on the page where buttonIndex != 0
So the result will look like this
[
{
"id": 1,
"pageTitle": "Python community",
"pageLink": "https://fairy-dev.io/python",
"visitCount": 5,
"buttonClickCount": 24
},
{
"id": 2,
"pageTitle": "Sequelize community",
"pageLink": "https://fairy-dev.io/sequelize",
"visitCount": 7,
"buttonClickCount": 57
}
]
I know I should use attributes and include but not sure what the exact answer is.
Any help would be appreciated.
Thanks in advance.
How can I avoid showing both the foreignKey that sequelize creates and the eagerly fetched object through includes?
I have the following model structure:
FormEntry:
owner: User
createdBy: User
modifiedBy: User
formEntryData: [FormEntryData]
I modeled it after reading through SequelizeJS docs and came up with the following:
const User = sequelize.define('user', {
id: {
type: Sequelize.BIGINT(20),
field: 'user_id',
primaryKey: true
},
emailAddress: {
type: Sequelize.STRING(256),
field: 'email_address'
}
}, {
tableName: 'users',
timestamps: false
});
const FormEntryData = sequelize.define('formEntryData', {
id: {
type: Sequelize.BIGINT(20),
field: 'id',
primaryKey: true
},
entryId: {
type: Sequelize.BIGINT(20),
field: 'entry_id'
},
...
}, {
tableName: 'formEntryData',
timestamps: false
});
const FormEntry = sequelize.define('formEntry', {
id: {
type: Sequelize.BIGINT(20),
field: 'entry_id',
primaryKey: true
},
...
}, {
tableName: 'formEntries',
timestamps: false
});
I then need to create the associations to tie the models together and after a lot of trial and error I came up with the following:
FormEntry.hasMany(FormEntryData, {foreignKey: 'entry_id', as: 'FormEntryData'});
FormEntry.belongsTo(User, {foreignKey: 'created_by', as: 'CreatedBy'});
FormEntry.belongsTo(User, {foreignKey: 'modified_by', as: 'ModifiedBy'});
FormEntry.belongsTo(User, {foreignKey: 'owner', as: 'Owner'});
I then was able to query the data by doing the following:
FormEntry.findByPrimary(1472280, {
include: [
{
model: FormEntryData,
as: "FormEntryData"
},
{
model: User,
as: "CreatedBy"
},
{
model: User,
as: "Owner"
},
{
model: User,
as: "ModifiedBy"
}
]
})
Unfortunately, my results seem kind of repetitive as it seems to be including both the foreign key and the object that is eagerly fetched.
{
"id": 1472280,
...
"created_by": 26508, <-- repetitive (don't want this)
"modified_by": 26508, <-- repetitive (don't want this)
"owner": null, <-- repetitive (don't want this)
"FormEntryData": [
{
"id": 27164476,
"entryId": 1472280, <-- repetitive (but I want this one)
...
"entry_id": 1472280 <-- repetitive (don't want this)
},
...
],
"CreatedBy": { <-- repetitive (but I want this one)
"id": 26508,
"emailAddress": "swaraj.kler#greywallsoftware.com"
},
"Owner": null, <-- repetitive (but I want this one)
"ModifiedBy": { <-- repetitive (but I want this one)
"id": 26508,
"emailAddress": "swaraj.kler#greywallsoftware.com"
}
}
You need to exclude specified fields from the query
FormEntry.findByPrimary(1472280, {
include: [
{
model: FormEntryData,
as: "FormEntryData",
attributes: { exclude: ['entry_id'] }
},
{
model: User,
as: "CreatedBy"
},
{
model: User,
as: "Owner"
},
{
model: User,
as: "ModifiedBy"
}
],
attributes: { exclude: ['owner', 'created_by', 'modified_by'] }
})
I am trying to pull an array from a different collection using collection2. I have been able to do this with objects using the following example for users:
users: {
type: String,
label: "Inspector",
optional: true,
autoform: {
firstOption: 'Choose an Inspector',
options: function() {
return Meteor.users.find({}, {
sort: {
profile: 1,
firstName: 1
}
}).map(function(c) {
return {
label: c.profile.firstName + " " + c.profile.lastName,
value: c._id
};
});
}
}
},
I would like to do the same but for an array of objects. Here is what the source data looks like:
{
"_id": "xDkso4FXHt63K7evG",
"AboveGroundSections": [{
"sectionName": "one"
}, {
"sectionName": "two"
}],
"AboveGroundItems": [{
"itemSection": "one",
"itemDescription": "dfgsdfg",
"itemCode": "dsfgsdg"
}, {
"itemSection": "two",
"itemDescription": "sdfgsdfg",
"itemCode": "sdfgsdgfsd"
}]
}
Here is what my function looks like:
agSection: {
type: String,
optional: true,
autoform: {
firstOption: 'Select A Section Type',
options: function() {
return TemplateData.find({}, {
sort: {
AboveGroundSections: 1,
sectionName: [0]
}
}).map(function(c) {
return {
label: c.AboveGroundSections.sectionName,
value: c.AboveGroundSections.sectionName
}
});
}
}
},
I know this, it's just not pulling the data for me. I am sure, I am just missing something small. I am trying to pull all objects within the AboveGroundSection array.
Your .map() is iterating over the set of documents but not over the arrays inside each document. Also I don't think your sorting is going to work the way you hope because of the inner nesting.
Try:
agSection: {
type: String,
optional: true,
autoform: {
firstOption: 'Select A Section Type',
options() {
let opt = [];
TemplateData.find().forEach(c => {
c.AboveGroundSections.forEach(s => { opt.push(s.sectionName) });
});
return opt.sort().map(o => { return { label: o, value: o } });
}
}
},
Also if your AboveGroundSections array only has a single key per element then you can simplify:
"AboveGroundSections": [
{ "sectionName": "one" },
{ "sectionName": "two" }
]
To:
"AboveGroundSections": [
"one",
"two"
]