In my Angular.js service I've created a custom request:
.factory('CalendarService', ['$resource',
function($resource) {
return {
Update: function(bookingObj) {
var BookingResource = $resource('http://localhost:1337/bookings/:id',{
id: '#id'
}, {
'update': {
method: 'PUT',
isArray: true
}
});
var bookingId = bookingObj.id;
return BookingResource.update({
id: bookingId
}, bookingObj).$promise;
}
On server side Sails.js seems properly configured with sails-mysql, I can make a get request with no errors, but when I call the update function I receive this error:
error: Sending 500 ("Server Error") response:
Error (E_UNKNOWN) :: Encountered an unexpected error
: .findOne() requires a criteria. If you want the first record try .find().limit(1)
at module.exports.findOne (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\adapter\dql.js:143:56)
at _runOperation (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\query\finders\operations.js:
400:29)
at run (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\query\finders\operations.js:69:8)
at bound.module.exports.findOne (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\query\finders
\basic.js:66:16)
at bound [as findOne] (C:\prestigeweb\node_modules\sails\node_modules\lodash\dist\lodash.js:729:21)
at Deferred.exec (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\query\deferred.js:501:16)
at updated (C:\prestigeweb\node_modules\sails\lib\hooks\blueprints\actions\update.js:83:9)
at bound (C:\prestigeweb\node_modules\sails\node_modules\lodash\dist\lodash.js:957:21)
at applyInOriginalCtx (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\utils\normalize.js:416:80)
at wrappedCallback (C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\utils\normalize.js:315:18)
at _normalizeCallback.callback.success (C:\prestigeweb\node_modules\sails\node_modules\waterline\node_modules\switchb
ack\lib\normalize.js:33:31)
at _switch (C:\prestigeweb\node_modules\sails\node_modules\waterline\node_modules\switchback\lib\factory.js:48:28)
at C:\prestigeweb\node_modules\sails\node_modules\waterline\lib\waterline\query\dql\update.js:224:9
at done (C:\prestigeweb\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:135:19)
at C:\prestigeweb\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:32:16
at C:\prestigeweb\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:157:25
Details: Error: .findOne() requires a criteria. If you want the first record try .find().limit(1)
This is the HTTP request from Postman:
PUT /bookings/6397 HTTP/1.1
Host: localhost:1337
Accept: application/json, text/plain, */*
Origin: http://localhost:8100
X-DevTools-Emulate-Network-Conditions-Client-Id: ABAC3370-A7E6-42AA-A5DA-BA0205880B9C
X-FirePHP-Version: 0.0.6
User-Agent: Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5
Content-Type: application/json;charset=UTF-8
DNT: 1
Referer: http://localhost:8100/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4,fr;q=0.2
Cache-Control: no-cache
Postman-Token: 0a627a0a-2f27-0e55-737f-5e838e1084e0
{"id":6397,bla bla bla}
this is how I configured Sails.js:
1) sails generate api bookings
2) npm-install sails-mysql
3) inserted in config/connections.js the following line
mysql: {
adapter: 'sails-mysql',
host: 'localhost',
port: 3306,
user: 'root',
password: '',
database: 'prestige'
},
4) added to config/cors.js:
allRoutes: true,
methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD'
origin: '*'
5) on config/model.js added
module.exports.models = {
connection: 'mysql',
migrate: 'safe'
};
The sails.js: model:
module.exports = {
tableName: 'prenotazioni',
adapter: 'mysql',
//migrate: 'safe',
autoCreatedAt: false,
autoUpdatedAt: false,
attributes: {
id: {
type: 'integer'
},
numero_prenotazione: {
type: 'string'
},
nome: {
type: 'string'
},
cognome: {
type: 'string'
},
civico: {
type: 'string'
},
indirizzo: {
type: 'string'
},
ditta: {
type: 'string'
},
cap: {
type: 'string'
},
citta: {
type: 'string'
},
nazione: {
type: 'string'
},
lingua: {
type: 'string'
},
telefono: {
type: 'string'
},
email: {
type: 'string'
},
agente: {
type: 'string'
},
numero_camere: {
type: 'integer'
},
numero_ospiti: {
type: 'integer'
},
costo_totale_camere: {
type: 'integer'
},
ospite_1: {
type: 'string'
},
ospite_2: {
type: 'string'
},
camera_1: {
type: 'string'
},
camera_2: {
type: 'string'
},
numero_persone_1: {
type: 'integer'
},
numero_persone_2: {
type: 'integer'
},
data_prenotazione: {
type: 'date'
},
data_arrivo_1: {
type: 'date'
},
data_arrivo_2: {
type: 'date'
},
data_partenza_1: {
type: 'date'
},
data_partenza_2: {
type: 'date'
},
quantita_1: {
type: 'integer'
},
quantita_2: {
type: 'integer'
},
totale_1: {
type: 'integer'
},
totale_2: {
type: 'integer'
},
prezzo_1: {
type: 'integer'
},
prezzo_2: {
type: 'integer'
},
status_1: {
type: 'integer'
},
status_2: {
type: 'integer'
},
duration: {
type: 'string'
}
}
};
In your model:
module.exports = {
...
autoPK: false,
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
...
}
}
Further reading: Waterline docs.
Related
Users Model defined like this.
const db = require ('../../config/db_config');
const users = db.sequelize.define('users', {
id: {
type: db.DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
first_name: {
type: db.DataTypes.STRING(150),
},
last_name: {
type: db.DataTypes.STRING(150),
},
email: {
type: db.DataTypes.STRING(256),
required: true,
unique: true
},
password: {
type: db.DataTypes.STRING,
},
student_id: {
type: db.DataTypes.STRING
},
status: {
type: db.DataTypes.BOOLEAN,
required: true,
defaultValue: 0
},
is_deleted: {
type: db.DataTypes.BOOLEAN,
required: true,
defaultValue: 0
},
createdAt: db.DataTypes.DATE,
updatedAt: db.DataTypes.DATE,
});
module.exports = users;
social_logins Model defined like this
const db = require ('../../config/db_config');
const socialLogins = db.sequelize.define('social_logins', {
id: {
type: db.DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
token: {
type: db.DataTypes.STRING
},
tokenType: {
type: db.DataTypes.STRING
},
fb_id: {
type: db.DataTypes.STRING
},
user_id: {
type: db.DataTypes.INTEGER
},
is_deleted: {
type: db.DataTypes.BOOLEAN,
required: true,
defaultValue: false
}
}, { underscored: true, timestamp: true, tableName: 'social_logins' });
module.exports = socialLogins;
User model associated with the social_logins model using belongsTo function
socialLoginsModel.belongsTo(users)
Sequelize throws eagerLoadingError
Error EagerLoadingError [SequelizeEagerLoadingError]: social_logins is
not associated to users!
While running this query given below.
const userModel = require ('./users_model');
const socialLoginModel = require('../social_logins/social_logins_model');
let id = "123456";
let email = "ex#example.com";
userModel.findOne({
where: { email },
include: [{
model: socialLogins,
where: {
fb_id: id
}
}]
});
you should have associations like this based on your model names
socialLogins.belongsTo(users) & users.hasOne(socialLogins)/ users.hasMany(socialLogins) based on your relations being defined in DB
here is my code
(node:10188) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: insert into user (email, name, password, role, username) values ('exam#mail.ru', 'chack', 'password', 'user', 'kkkp') - ER_BAD_FIELD_ERROR: Unknown column 'role' in 'field list'
(node:10188) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
'use strict';
const Model = require('objection').Model;
const AppConstants = require('./../constants');
class user extends Model {
static get tableName() {
return 'user';
}
static get jsonSchema() {
return {
type: 'object',
required: ['username', 'password', 'email', 'name'],
properties: {
id: { type: 'integer' },
username: {type: 'string',
unique: true ,
minlength: AppConstants.USERNAME_MIN_LENGTH,
maxlength: AppConstants.USERNAME_MAX_LENGTH
},
password: {
type: 'string',
minlength: AppConstants.PASSWORD_MIN_LENGTH,
maxlength: AppConstants.PASSWORD_MAX_LENGTH
},
email: { type: 'string',
index: { unique: true },
},
name: { type: 'string'
},
role: { enum: ['admin', 'user'], ///////////// here is
default: 'user'
}
}
};
}
}
You forgot to assign a type to the role field. Try this, please:
'use strict';
const Model = require('objection').Model;
const AppConstants = require('./../constants');
class user extends Model {
static get tableName() {
return 'user';
}
static get jsonSchema() {
return {
type: 'object',
required: ['username', 'password', 'email', 'name'],
properties: {
id: {type: 'integer'},
username: {
type: 'string',
unique: true,
minlength: AppConstants.USERNAME_MIN_LENGTH,
maxlength: AppConstants.USERNAME_MAX_LENGTH
},
password: {
type: 'string',
minlength: AppConstants.PASSWORD_MIN_LENGTH,
maxlength: AppConstants.PASSWORD_MAX_LENGTH
},
email: {
type: 'string',
index: {unique: true},
},
name: {
type: 'string'
},
role: {
type: 'string',
enum: ['admin', 'user'], ///////////// here is
default: 'user'
}
}
};
}
}
I need to run a join query using sequelize and I have been reading the documentation at sequelize doc. But as I run the following snippet, I get an error.
let channelUsersM = UserModel.get(); // Table name: channel_users
let channelM = ChannelModel.get(); // Table name: channel
channelUsersM.belongsTo(channelM, {as: 'channel',foreign_key: 'channel_id',targetKey:'id'});
channelM.hasMany(channelUsersM,{foreign_key: 'channel_id'});
channelUsersM.findAll({
attributes: ['username'],
where: {
usertype: this.userType,
channel: {
name: channelName
}
},
include: [channelM]
}).then((r) => {
resolve(r);
}).catch((err) => {
reject(err);
});
Error says: channel is not associated to channel_users!
What could be the reason for this? I know how to directly run a SQL query using sequelize, but I do not want to go with it.
For easier understanding here, is the equivalent sql query that I am trying with sequelize:
select cu.username from channel as ch left join
channel_users as cu on ch.id = cu.channel_id
ch.name = 'some-name' and cu.usertype = 'some-type';
Here is the definition of models if required:
For channel_users:
channel_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
field: 'channel_id'
},
userid: {
type: Sequelize.INTEGER,
field: 'userid'
},
username: {
type: Sequelize.CHAR(255),
field: 'username'
},
password: {
type: Sequelize.TEXT,
field: 'password'
},
usertype: {
type: Sequelize.ENUM('user', 'moderator','speaker','owner'),
field: 'usertype'
}
For channel:
id: {
type: Sequelize.INTEGER,
field: 'id',
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.CHAR(255),
field: 'name'
},
display_name: {
type: Sequelize.TEXT,
field: 'display_name'
},
creatorid: {
type: Sequelize.INTEGER,
field: 'creatorid'
},
password: {
type: Sequelize.TEXT,
field: 'password'
},
createdAt: {
type: Sequelize.DATE,
field: 'createdAt'
},
modifiedAt: {
type: Sequelize.DATE,
field: 'modifiedAt'
}
You have defined an alias in the belongsTo association, so you also need to include the alias in include attribute when querying. Moreover, the channel.name column value should also be included in the include object of the query.
channelUsersM.findAll({
attributes: ['username'],
where: {
usertype: this.userType
},
include: [
{
model: channelM,
as: 'channel',
attributes: [],
where: { name: channelName }
}
]
}).then((r) => {
resolve(r);
}).catch((err) => {
reject(err);
});
The attributes: [] in include is added in order to prevent returning any fields from the channel table (according to you query you want only the username field from channel_users table).
Unhandled rejection TypeError: undefined is not a function
error whe i am trying to update my table in sequelize above MySQL.
here is the snippet of code that triggering the error with commented one that surprisingly works:
topic.update(
{ name: "adfa"},
{ where: { tid: 1} }
);
//topicAttribute.update({ value: "name 2"},{where: {TOPIC: 2,name: "nadpis" }});
Now this is my two models:
var topic = sequelize.define('topic', {
tid: { type: Sequelize.INTEGER,
field: 'tid',
primaryKey: true
},
name: { type: Sequelize.STRING,
field: 'name'
},
added: { type: Sequelize.DATE,
field: 'added'
},
addedBy: { type: Sequelize.STRING,
field: 'added_by'
},
changed: { type: Sequelize.DATE,
field: 'changed'
},
changedBy: { type: Sequelize.STRING,
field: 'changed_by'
},
parent: { type: Sequelize.INTEGER,
field: 'parent'
},
enabled: {
type: Sequelize.BOOLEAN,
field: 'enabled'
}
},
{
tableName: 'topic',
timestamps: false
});
var topicAttribute = sequelize.define('tAttribute', {
parent: { type: Sequelize.INTEGER,
field: 'TOPIC',
primaryKey: true
},
name: { type: Sequelize.STRING,
field: 'name',
primaryKey: true
},
value: { type: Sequelize.STRING,
field: 'value'
},
},
{
tableName: 'topic_attribute',
timestamps: false
});
topic.hasOne(topic, {foreignKey: 'tid'});
topic.hasMany(topicAttribute, {foreignKey: 'parent'});
topicAttribute.belongsTo(topic, {foreignKey: 'parent'});
And finally my stacktrace:
Unhandled rejection TypeError: undefined is not a function
at Instance.set (C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\instance.js:365:16)
at Instance.set (C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\instance.js:293:16)
at initValues (C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\instance.js:63:8)
at Instance (C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\instance.js:107:14)
at new Instance (C:\Users\212443162\Documents\ithd\node_modules\sequelize\li b\model.js:655:14)
at Model.build (C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\model.js:1493:10)
at C:\Users\212443162\Documents\ithd\node_modules\sequelize\lib\model.js:2119:24
at tryCatcher (C:\Users\212443162\Documents\ithd\node_modules\sequelize\node_modules\bluebird\js\main\util.js:24:31)
at Function.Promise.attempt.Promise.try (C:\Users\212443162\Documents\ithd\node_modules\sequelize\node_modules\bluebird\js\main\method.js:31:24)
at Model.update (C:\Users\212443162\Documents\ithd\node_modules\sequelize\li b\model.js:2116:21)
at C:\Users\212443162\Documents\ithd\routes\topics.js:119:8 at Layer.handle [as handle_request] (C:\Users\212443162\Documents\ithd\node_ modules\express\lib\router\layer.js:95:5)
at next (C:\Users\212443162\Documents\ithd\node_modules\express\lib\router\r oute.js:131:13)
at Route.dispatch (C:\Users\212443162\Documents\ithd\node_modules\express\li b\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\212443162\Documents\ithd\node_ modules\express\lib\router\layer.js:95:5)
at C:\Users\212443162\Documents\ithd\node_modules\express\lib\router\index.j s:277:22
I'm bangin' my head against the wall in the last hours, and I can't figure out a solution to my problem. In my sails models, I have 2 one-to-many associations. 'A' model can have many 'B', and 'B' model can have many 'C'. In my controller, when I do a.find().populate('b') (...) it returns me the entire collection of A model, but populate each entry of A model with only one B, which doesn't match the current dataset I have in my database(mysql). And doesn't populate the C entries in the B model. In other words, I'm trying to achieve something like nested population.
It's something wrong with the Controller code, right? How can I make this work?
Thanks in advance!
EDIT:
Company.js
module.exports = {
identity: 'company',
attributes: {
name: {
type: 'string',
required: true
},
address: {
type: 'string',
required: true
},
zip_code: {
type: 'string',
required: true
},
city: {
type: 'string',
required: true
},
nif: {
type: 'integer',
required: true,
minLength: 9
},
country: {
type: 'string',
required: true
},
phone_number: {
type: 'string',
required: true
},
email: {
type: 'email',
required: true
},
facilities: {
collection: 'facility',
references: 'facility',
on: 'id',
via: 'company'
}
}
};
Facility.js
module.exports = {
identity: 'facility',
attributes: {
company: {
columnName: 'id_company',
model: 'company'
},
warehouses: {
collection: 'warehouse',
references: 'warehouse',
on: 'id',
via: 'facility'
},
name: {
type: 'string',
required: true
},
address: {
type: 'string',
required: true
},
zip_code: {
type: 'string',
required: true
},
city: {
type: 'string',
required: true
},
country: {
type: 'string',
required: true
},
phone_number: {
type: 'string',
},
email: {
type: 'email',
},
longitude: {
type: 'float',
},
latitude: {
type: 'float'
}
}
};
Warehouse.js
module.exports = {
identity: 'warehouse',
attributes: {
facility: {
columnName: 'id_facility',
model: 'facility',
},
name: {
type: 'string',
required: true
},
longitude: {
type: 'float',
},
latitude: {
type: 'float'
}
}
};
MainController's relevant code:
companies: function(req, res) {
company.find().populate('facilities').exec(function(err, comp){
var error = '';
if(err){
error = 'Unable to retrieve the requested information. Try again later and, if the problem persists, contact the platform administrator.';
} else if(!comp[0]) {
error = 'There\'s no company data inserted.';
}
// (...)
});
},
You should remove the references and on from your models.
Regarding nested population, just like I said in the comment, Waterline does not currently support it. You could check Waterline2 which, as they say, offers the possibility of nested populating, but is not recommended for production.
Otherwise you could check this out: Sails.js populate nested associations