Sequelize include return data - node.js

I am using Sequelize express with Node.js as the backend. I have models Event and models buyer with relation many to many
Model Event:
module.exports = function (sequelize, DataTypes) {
var Event = sequelize.define("Event", { //...},
{
tableName: 'event',
timestamps: false,
freezeTableName: true,
classMethods: {
associate: function (models) {
Event.hasMany(models.Meetings, {foreignKey: 'event_id'});
Event.belongsToMany(models.Buyer, {
through: 'BuyerPresent'});
Event.belongsToMany(models.Seller, {
through: 'SellerPresent'});
}
}
});
return Event;
};
Model Seller:
module.exports = function (sequelize, DataTypes) {
var Seller = sequelize.define("Seller", { //...
}, {
tableName: 'seller',
timestamps: false,
freezeTableName: true,
classMethods: {
associate: function (models) {
Seller.hasMany(models.Meetings, {foreignKey: 'seller_id'});
Seller.belongsToMany(models.Event, {
through: 'SellerPresent'});
}
}
});
return Seller;
};
I run the query and send the data with
res.render('path', {'results':seller})
:
function findIdSeller(selectEvent) {
var match = {
where: {
event: selectEvent
},
// include: {
// model: Seller
// },
include: [{
model: Seller,
nested: false
}],
// plain:true
raw: true
};
return models.Event.findAll(match)
}
exports.findDataSellerPromise = function (selectEvent) {
return findIdSeller(selectEvent).then(function (result) {
return result.map(function(seller) {
console.log('SELLINFO: ', seller);
return seller;
});
});
};
In the terminal i received:
{
id: 4,
incoming: 2,
event: 4,
'Sellers.id': 1,
'Sellers.name_firm': 'kdm srl',
'Sellers.site': 'www.terrebasse.com'
}
How can I return an item as:
{
id: 4,
incoming: 2,
event: 4,
Sellers: {
id': 1,
name_firm: 'kdm srl',
site: 'www.terrebasse.com'
}
}

Remove the raw: true from the query
That would give sellers as instance on each event
Something like
{
//Event1 properties
Sellers: {
// Associated sellers properties
}
}
Guess I am too late to the party..
But for anyone else facing similar issue

Related

Show specific columns with dataloader-sequelize in nested tables

Currently I have some models. I'm using graphql with dataloader-sequelize and it works fine as long as I show associated tables without third level.
My models:
"articulo.js"
'use strict';
module.exports = (sequelize, DataTypes) => {
const Articulo = sequelize.define(
'articulos',
{
art_codigo: {
type: DataTypes.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true
},
art_nombre: DataTypes.STRING(255),
art_longitud: DataTypes.STRING(250),
art_latitud: DataTypes.STRING(250),
.....[more columns]
art_contenido: DataTypes.TEXT,
},
{
timestamps: false,
freezeTableName: true,
name: {
singular: 'Articulo',
plural: 'Articulos',
},
indexes: [
{
unique: true,
fields: ['art_codigo'],
},
],
}
);
Articulo.associate = (models) => {
Articulo.belongsTo(models.canalizados,
{
foreignKey: 'art_canalizado',
as:"Canalizado",
}
);
Articulo.belongsTo(
models.articulos_tipos,
{
foreignKey: 'art_tipo'
}
);
};
return Articulo;
};
articulo_tipo.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const ArticuloTipo = sequelize.define('articulos_tipos', {
ari_codigo: {
type: DataTypes.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true
},
ari_nombre: DataTypes.STRING(255),
}, {
timestamps: false,
freezeTableName: true,
name: {
singular: 'ArticuloTipo',
plural: 'ArticulosTipos',
},
indexes: [
{
unique: true,
fields: ['ari_codigo'],
},
],
});
ArticuloTipo.associate = (models) => {
ArticuloTipo.hasMany(models.articulos)
};
return ArticuloTipo;
};
canalizado.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Canalizado = sequelize.define('canalizados', {
cnl_codigo: {
type: DataTypes.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true
},
cnl_fecha_alta: DataTypes.DATE,
...... [more columns]
cnl_revisado: DataTypes.BOOLEAN,
}, {
timestamps: false,
freezeTableName: true,
name: {
singular: 'Canalizado',
plural: 'Canalizados',
},
indexes: [
{
unique: true,
fields: ['cnl_codigo'],
},
],
}
);
Canalizado.associate = (models) => {
Canalizado.hasMany(models.articulos);
Canalizado.belongsTo(
models.canalizados_tipos,
{
foreignKey: 'cnl_tipo',
}
);
};
return Canalizado;
};
canalizado_tipo.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const CanalizadoTipo = sequelize.define('canalizados_tipos', {
cai_codigo: {
type: DataTypes.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true
},
cai_nombre: DataTypes.STRING(50)
}, {
timestamps: false,
freezeTableName: true,
tableName: "canalizados_tipos",
name: {
singular: 'CanalizadoTipo',
plural: 'CanalizadosTipo',
},
indexes: [
{
unique: true,
fields: ['cai_codigo'],
},
],
});
CanalizadoTipo.associate = (models) => {
CanalizadoTipo.hasMany(models.canalizados)
};
return CanalizadoTipo;
};
My resolvers:
articulo.js
const Sequelize = require('sequelize');
const {detectarCampos} = require('../_extra/comunes'); //Optimize which columns you want to use in graphql
const Op = Sequelize.Op;
const resolvers = {
Articulo:{
art_tipo: (parent, args, { models, options }, info) => {
return parent.getArticuloTipo(options); //It's an internal getter from sequelize, isn't it?
},
art_canalizado: (parent, args, { models, options }, info) => {
return parent.getCanalizado(options); //It's an internal getter from sequelize, isn't it?
},
},
Query: {
async getArticulo(root, { codigo }, { models }, info) {
return models.articulos.findByPk(
codigo,
{attributes: detectarCampos(info),}
);
},
async getArticulos(root, { nombre, tipo}, { models, options }, info) {
var whereStatement = {};
if(nombre){
whereStatement.art_nombre = {[Op.like]: '%' + nombre + '%'};
}
if (tipo){
whereStatement.art_tipo = tipo;
}
return models.articulos.findAll({
attributes: detectarCampos(info),
where: whereStatement,
//limit: 10,
options
});
},
async getAllArticulos(root, args, { models }, info) {
return models.articulos.findAll( {
attributes: detectarCampos(info),
limit: 10,
});
},
},
Mutation: {
},
}
module.exports = resolvers
canalizado.js
const {detectarCampos} = require('../_extra/comunes');
const resolvers = {
Canalizado:{
cnl_tipo: (parent, args, { models, options }, info) => {
return parent.getCanalizadoTipo(options)
},
},
Query: {
async getCanalizado(root, { codigo }, { models, context }, info) {
return await models.canalizados.findByPk(codigo,
{attributes: detectarCampos(info),});
},
async getCanalizados(root, { tipo }, { models, options }, info) {
var whereStatement = {};
if (tipo)
whereStatement.cnl_tipo = tipo;
return models.canalizados.findAll({
attributes: detectarCampos(info),
where: whereStatement,
limit: 2,
options
});
},
async getAllCanalizados(root, args, { models, options }) {
return models.canalizados.findAll({
attributes: detectarCampos(info),
limit: 100,
options
});
},
},
Mutation: {
},
}
module.exports = resolvers
It works fine if I search in graphql with this sentence:
query{
getArticulos(tipo:2){
art_codigo
art_nombre
art_tipo{
ari_nombre
}
art_latitud
art_longitud
}
}
Executing (default): SELECT [art_codigo], [art_nombre], [art_tipo], [art_latitud], [art_longitud] FROM [articulos] AS [articulos] WHERE [articulos].[art_tipo] = 2;
Executing (default): SELECT [ari_codigo], [ari_nombre] FROM [articulos_tipos] AS [articulos_tipos] WHERE [articulos_tipos].[ari_codigo] IN (2);
On the other hand, if I try to look for in a deeper level, I get automatic names from columns I don't need to use:
query{
getArticulos(tipo:2){
art_codigo
art_nombre
art_tipo{
ari_nombre
}
art_canalizado{
cnl_codigo
}
art_latitud
art_longitud
}
}
Executing (default): SELECT [art_codigo], [art_nombre], [art_tipo], [art_latitud], [art_longitud] FROM [articulos] AS [articulos] WHERE [articulos].[art_tipo] = 2;
Executing (default): SELECT [ari_codigo], [ari_nombre] FROM [articulos_tipos] AS [articulos_tipos] WHERE [articulos_tipos].[ari_codigo] IN (2);
Executing (default): SELECT [cnl_codigo], [cnl_fecha_alta], [........], [cnl_revisado], [cnl_tipo], [cnl_fuente], [cnl_autor], [CanalizadoTipoCaiCodigo] FROM [canalizados] AS [canalizados] WHERE [canalizados].[cnl_codigo] IN (51357, 51365, 51379, [........], 63910);
In this case, in Graphql returns this error:
"message": "Invalid column name 'CanalizadoTipoCaiCodigo'.",
How can I ommite that field?? Could I use something like "attributes" to specify which attributes I'd like to show?? I tried to use it in resolvers, models... but always with no success
This error is the same if I look for a deep level:
query{
getArticulos(relevancia:2){
art_codigo
art_nombre
art_tipo{
ari_nombre
}
art_canalizado{
cnl_codigo
cnl_tipo{
cai_nombre
}
}
art_latitud
art_longitud
}
}
Any idea about my problem? Everrything is wellcome!!
UPDATE
server.js
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const typeDefs = require('./configuracion/schema/typeDefs')
const resolvers = require('./configuracion/schema/resolvers')
const models = require('./configuracion/models')
const { createContext, EXPECTED_OPTIONS_KEY } = require('dataloader-sequelize');
const dataloaderContext = createContext(models.sequelize);
//const server = new ApolloServer({ typeDefs, resolvers, context: { models } });
const server = new ApolloServer({
typeDefs,
resolvers,
context: async () => ({
models,
options: { [ EXPECTED_OPTIONS_KEY ]: dataloaderContext },
}),
});
const app = express();
server.applyMiddleware({ app });
models.sequelize.authenticate().then((err) => {
console.log('*** MSG [server.js]: Successful Connection');
})
.catch((err) => {
console.log('*** ERROR [server.js]: No ha sido posible conectarse a la base de datos', err);
})
//models.sequelize.sync();
app.listen({ port: 3000 }, () =>
console.log(`** API ready at http://localhost:3000${server.graphqlPath} `)
);
configuracion/models/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
//const env = process.env.NODE_ENV || 'development';
const config = require('../config_sqlserver')
const db = {};
const sequelize = new Sequelize(config.db_database, config.db_user, config.db_password,
{
host: config.db_host,
port: config.DB_PORT, // <----------------The port number you copied
dialect: "mssql",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
//const model = sequelize['import'](path.join(__dirname, file));
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
resolver > articulo_tipo.js
const Sequelize = require('sequelize');
const {detectarCampos} = require('../_extra/comunes');
const Op = Sequelize.Op;
const resolvers = {
Query: {
async getArticuloTipo(root, { codigo }, { models, context }, info) {
return await models.articulos_tipos.findByPk(codigo, { attributes: detectarCampos(info)},);
},
async getArticulosTipos(_, { nombre, tipo }, { models }, info) {r
var whereStatement = {};
if(nombre)
whereStatement.ari_nombre = {[Op.like]: '%' + nombre + '%'};
if(tipo)
whereStatement.ari_codigo = tipo;
return models.articulos_tipos.findAll({
attributes: detectarCampos(info),
where: whereStatement,
});
},
async getAllArticulosTipos(root, args, { models }) {
return models.articulos_tipos.findAll()
},
},
Mutation: {
},
}
module.exports = resolvers
I don't use sequelize ... but I probably can point you in the right direction:
attributes are used already...
maybe not exactly the way you need ...
check what is returned from detectarCampos(info) in resolvers
Probably you'll find that info is undefined ... sometimes info is missing... why!?
art_canalizado: (parent, args, { models, options }, info) => {
return parent.getCanalizado(options); //It's an internal getter from sequelize, isn't it?
},
getCanalizado is called with options while normally it should be called with more arguments:
async getCanalizado(root, { codigo }, { models, context }, info) {
Fix:
Pass missging arguments - it should work (if detectarCampos works, of course).

SequelizeJS, Is this a best way to create this JSON Result using this models

I want this result, but, is so complicated do to this in this way. There is a better way to create this result using Sequelize. Using the querys tools of sequelize to aggregate results from diferent tables, on JPA the only thing i do is annotate with join table and pass the columns ad invese columns values.
[
{
"id": 1,
"codemp": "999",
"nome": "A3 Infortech",
"limiteInstancias": "10",
"instancias": []
},
{
"id": 2,
"codemp": "92",
"nome": "Endovideo",
"limiteInstancias": "20",
"instancias": [
{
"id": 198211,
"ipLocal": "40.0.10.11",
"ipExterno": "187.33.230.106",
"hostname": "FATURAMENTO-PC",
"dataCriacao": "2019-07-01T21:40:29.000Z"
}
]
},
{
"id": 6,
"codemp": "103",
"nome": "SOS Otorrino",
"limiteInstancias": "999",
"instancias": [
{
"id": 199127,
"ipLocal": "192.168.11.101",
"ipExterno": "000.000.000.000",
"hostname": "Guiche3-PC",
"dataCriacao": "2019-07-01T21:40:32.000Z"
},
{
"id": 199164,
"ipLocal": "192.168.25.209",
"ipExterno": "000.000.000.000",
"hostname": "Consultorio06",
"dataCriacao": "2019-07-01T21:40:29.000Z"
}
]
},
{
"id": 15,
"codemp": "162",
"nome": "Clinica Vida e Saude",
"limiteInstancias": "10",
"instancias": [
{
"id": 199774,
"ipLocal": "192.168.56.1",
"ipExterno": "000.000.000.000",
"hostname": "ALEXANDRELEAL",
"dataCriacao": "2019-07-01T21:40:28.000Z"
}
]
}
]
I have this codes:
Empresa Model
module.exports = (sequelize, DataTypes) => {
const empresa = sequelize.define("empresa", {
id: {
type: DataTypes.BIGINT(20),
primaryKey: true,
field: "id"
},
codemp: {
type: DataTypes.INTEGER,
field: "codemp"
},
nome: {
type: DataTypes.STRING,
field: "nome"
},
limiteInstancias: {
type: DataTypes.INTEGER,
field: "limite_instancias"
}
}, {
timestamps: false,
freezeTableName: true,
tableName: "empresa"
});
empresa.associate = (db) => {
console.log(db);
empresa.hasMany(db.instanciaEmpresa, {foreignKey: "id_empresa"});
};
return empresa;
};
Instancia Model
module.exports = (sequelize, DataTypes) => {
const instancia = sequelize.define("instancia", {
id: {
type: DataTypes.BIGINT(20),
primaryKey: true,
field: "id"
},
ipLocal: {
type: DataTypes.STRING,
field: "ip_local"
},
ipExterno: {
type: DataTypes.STRING,
field: "ip_externo"
},
hostname: {
type: DataTypes.STRING,
field: "hostname"
},
dataCriacao: {
type: DataTypes.DATE,
field: "data_criacao"
},
}, {
timestamps: false,
freezeTableName: true,
tableName: "instancia"
});
instancia.associate = (db) => {
console.log(db);
instancia.belongsTo(db.empresa, {foreignKey: "id_instancia"});
};
return instancia;
};
InstanciaEmpresa Model
module.exports = (sequelize, DataTypes) => {
const instanciaEmpresa = sequelize.define("instancia_empresa", {
idEmpresa: {
type: DataTypes.BIGINT(20),
primaryKey: true,
field: "id_empresa"
},
idInstancia: {
type: DataTypes.BIGINT(20),
primaryKey: true,
field: "id_instancia"
},
}, {
timestamps: false,
freezeTableName: true,
tableName: "instancia_empresa"
});
return instanciaEmpresa;
};
My Database diagram.
A picture of my database diagram
The code of my response
const db = require("../config/db.config");
const empresa = db.empresa;
const instancia = db.instancia;
const instanciaEmpresa = db.instanciaEmpresa;
const empressaResult = [];
module.exports = {
async getAll(req, res) {
return res.send(await getAllEmpresa());
}
};
async function getAllEmpresa() {
//Recover all companies from the table
let empresaList = await empresa.findAll({raw: true});
//I browse the array of companies to retrieve the instances associated with the company
for(let i = 0; i < empresaList.length; i++){
//Create the atribute Instancias[]
empresaList[i].instancias = [];
//I retrieve the list of associated instances in the InstanciaEmpresa table
let instanciasEmpresa = await instanciaEmpresa.findAll({where: {"id_empresa": empresaList[i].id}, raw: true});
//Verify if existes any item of InstanciaEmpresa
if(instanciasEmpresa.length > 0){
//If there is a run through list of instances
for(let j = 0; j < instanciasEmpresa.length; j++){
//I retrieve the Instancia in the database and add it to the company Instancias list
let inst = await instancia.findByPk(instanciasEmpresa[j].idInstancia, {raw: true});
empresaList[i].instancias.push(inst);
}
}
//I add the company with the instances in a result list;
empressaResult.push(empresaList[i]);
}
return empressaResult;
}
You can use include option to operate join on your tables.
Then your code would look like,
const empresaList = await empresa.findAll({
raw: true,
include: [
{
model: instancias,
required: false, // left join, `true` means inner join.
}
]
});
As you can see, you can pass array of { model, required } into include option.
You can set required to true if you want to operate inner join else it would operate left join.
--- ADDED ---
SequelizeEagerLoadingError: instancia is not associated to empresa means you're not calling associate function on db initialization.
You can write helper function like below in your db.js.
addAssociations(name) {
if (this[name].associate) {
this[name].associate(this);
}
}
}
and use it like
/*
* this.models = [
* {
* name: 'instancias',
* model: instancias,
* },
* ... and many more
* ]
*/
this.models.forEach((value) => {
this.addAssociations(value.name);
});

How to join two tables? - Cannot read property 'getTableName' of undefined

Users Model File
'use strict';
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('user', {
"access_role_id":DataTypes.INTEGER,
"user_type":{
type: DataTypes.ENUM,
values: ['A', 'V', 'U']
},
"login_access":{
type: DataTypes.ENUM,
values: ['APP', 'WEB', 'BOTH']
},
"username": DataTypes.STRING,
"email": DataTypes.STRING,
"updated_at":DataTypes.DATE,
"created_at":DataTypes.DATE,
}, {
"timestamps": false,
"createdAt": false,
'updatedAt': false,
"underscored": true,
"freezeTableName": false,
});
user.associate = function(models) {
// associations can be defined here
models.user.belongsTo(models.product, {targetKey: 'id',foreignKey: 'created_by'});
};
return user;
};
User Controller File
const dbConfig = require( '../../../db/models/index');
let users =require('../../../db/models/user')(dbConfig.sequelizeDB,dbConfig.Sequelize);
module.exports = {
// GET /customer/:id
getCustomer: function(req, res, next) {
users.findAll({
include: [{
model: users.product,
}]
}).then(function (stores) {
if (stores.length === 0) {
res.json('There are no stores in the database');
}
res.json(stores);
});
},
};
I am unable to get the product table data. It always shows an error:
Unhandled rejection TypeError: Cannot read property 'getTableName' of undefined.
Why the product table is not fetched in users model? How can I access this product table data by the users model?
Update your User Controller File as
const dbConfig = require( '../../../db/models/index');
let users =require('../../../db/models/user')(dbConfig.sequelizeDB,dbConfig.Sequelize);
let product=require('../../../db/models/product')(dbConfig.sequelizeDB,dbConfig.Sequelize);
module.exports = {
// GET /customer/:id
getCustomer: function(req, res, next) {
users.findAll({
include: [{
model: product,
}]
}).then(function (stores) {
if (stores.length === 0) {
res.json('There are no stores in the database');
}
res.json(stores);
});
},
};

sequelize.js association accessor

I made API server with Node.js
Also I use sequelize.js(version 4) for communicate with MySQL.
My table structure is here.
[Article]
no(PK)
subject
content
created_at
updated_at
[Comment]
no(PK)
content
created_at
updated_at
article_no(FK to Article)
[index.controller.js]
import { Article, Comment } from '../model/model';
export const index = (req, res) => {
res.send('controller index');
};
export const getArticle = (req, res) => {
try {
Article.all()
.then(article => {
res.status(200).json({status: true, result: article});
});
} catch(e) {
res.status(500).json({status: false, result: "get article fail"});
}
}
export const addArticle = (req, res) => {
const { subject, content } = req.body;
try {
Article.create({
subject: subject,
content: content
})
res.status(200).json({status: true, result: "article write success"});
} catch(e) {
res.status(500).json({status: false, result: "article fail"});
}
}
export const getComment = (req, res) => {
try {
Comment.all()
.then(comment => {
res.status(200).json({status: true, result: comment})
});
} catch(e) {
res.status(500).json({status: false, result: "get comment fail"});
}
}
export const addComment = (req, res) => {
const { content, article_no } = req.body;
try {
Comment.create({
content: content,
article_no: article_no
})
.then(() => res.status(200).json({status: true, result: "comment write success"}))
} catch(e) {
console.log(e);
res.status(500).json({status: false, result: "comment fail"});
}
}
[index.js]
import express from 'express';
import { index, getArticle, getComment,addArticle, addComment } from './index.controller';
const router = express.Router();
router.get('/', index);
router.get('/article', getArticle);
router.post('/article', addArticle);
router.get('/comment', getComment);
router.post('/comment', addComment);
export default router;
[model.js]
import Sequelize from 'sequelize';
const sequelize = new Sequelize('db', 'id', 'pw', {
host: '127.0.0.1',
dialect: 'mysql'
})
export const Article = sequelize.define('article', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
subject: {
type: Sequelize.STRING,
allowNull: false
},
content: {
type: Sequelize.STRING,
allowNull: false
}
}, {
freezeTableName: true,
underscored: true
})
export const Comment = sequelize.define('comment', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
content: {
type: Sequelize.STRING,
allowNull: false
}
}, {
freezeTableName: true,
underscored: true
})
Article.hasMany(Comment, {as: 'Comments'}); // association
Comment.belongsTo(Article); // association
sequelize.sync({
force: false
});
Because of association(hasMany, belongsTo), article_no column will be added to Comment table.
Refer to this document, http://docs.sequelizejs.com/manual/tutorial/associations.html#one-to-many-associations-hasmany-
It says that Instances of Project will get the accessors getWorkers and setWorkers.
In my case, it will be getComments and setComments.
But I don't know exactly how can I get all the comments related articles with using accessor.
Current output is here. (If I connect to GET /article)
{
"status":true,
"result":[
{
"no":1,
"content":"comment test",
"created_at":"2018-07-18T05:00:45.000Z",
"updated_at":"2018-07-18T05:00:45.000Z",
"article_no":1
}
]
}
Desired output is here
{
"status":true,
"result":[
{
"no":1,
"content":"comment test",
"created_at":"2018-07-18T05:00:45.000Z",
"updated_at":"2018-07-18T05:00:45.000Z",
"article_no":1,
"comments": [
// related comments here!
]
}
]
}
Thanks.
When you want to join another model you should use include in your query
User.findAll({
include: [
{ model: Profile, required: true // inner join }
],
limit: 3
});
Check out the Sequelize model usage docs.
To access the comments with accessors you will need do something like this:
const articles = await Article.all();
articles.forEach(article => {
const comments = await article.getComments();
})
The idea behind is that each article sequelize object will have the accessor getComments but internally what it does when you execute getComments it makes a new request to the database with the prepopulated articleId in the comments where query. This is called lazy loading because you can load the data when you need it. But that is not your case.
For the desired output I suggest to use the include method cause it will make a single request to the database.

Non mapped properties - Sequelize

The supports are: React, Redux and Sequelize.
Basically I want to be able to mark an object as being dirty when the Redux store gets updated.
function updateCar(carToUpdate, car) {
switch(car[1]) {
case "models":
carToUpdate.models = car[3];
carToUpdate.setDirty();
break;
}
};
Then when someone clicks a save button, I want to only update those models that have their dirty flag set to true
var state = request.body;
state.forEach(function (car) {
if (car && car.isDirty) {
updateCar(car);
}
}
Now I have following model for the car:
module.exports = function (sequelize, DataTypes) {
var Cars = sequelize.define('Cars',
{
name: DataTypes.STRING,
type: DataTypes.INTEGER,
models: DataTypes.INTEGER,
//Next is NOT working, this does not make it non-mapped
isDirty: {
type: DataTypes.BOOLEAN,
scope: false
},
},
{
classMethods: {
associate: function (models) {
// associations can be defined here
}
},
instanceMethods: {
setDirty: function() {
this.isDirty = true;
}
}
});
return Cars;
};
Anyone who has experience with non-mapped fields or something similar?
Found it eventually.
The model of the car should contain a VIRTUAL property:
module.exports = function (sequelize, DataTypes) {
var Cars = sequelize.define('Cars',
{
name: DataTypes.STRING,
type: DataTypes.INTEGER,
models: DataTypes.INTEGER,
isDirty: {
type: DataTypes.VIRTUAL
},
},
{
classMethods: {
associate: function (models) {
// associations can be defined here
}
}
});
return Cars;
};
Next the flag should be set when updating the values:
function updateCar(carToUpdate, car) {
switch(car[1]) {
case "models":
carToUpdate.models = car[3];
carToUpdate.isDirty = true;
break;
}
};
Then the save method can check the isDirty flag
var state = request.body;
state.forEach(function (car) {
if (car && car.isDirty) {
console.log(car.name +": "+ car.isDirty);
updateCar(car);
}
}, this);
Last but not least, we reset the isDirty flag to false so we do not update the same models over and over.
var save = function () {
var state = carStore.getState();
return $.ajax({
url: "/Cars/update",
data: JSON.stringify(state),
method: "POST",
contentType: "application/json"
}).then(function() {
carStore.dispatch({
type: 'resetDirty',
data: null
});
});
};
And the dispatch method for resetting the flag:
function updateReducer(state, action) {
switch (action.type) {
case 'load':
return action.data;
case 'update':
return updateCars(action.carChanges, state);
case 'resetDirty':
return resetDirtyFlags(state);
default:
return action.data;
}
}
function resetDirtyFlags(state) {
var newState = $.extend(true, [], state);
if(state) {
newState.forEach(function(car) {
car.isDirty = false;
}, this);
return newState;
}
return newState;
}

Resources