The title may not be clear, but what I want to achieve is to have Categories with parentCategories. For example:
/-Clothes
/---Men
/---Women
/---Kids
/-----Newborns
So I thought I could make every category have an optional parent category and whenever I add a category with a parent one, find this parent category and add the new subCategory to it as well. Am I clear?
This is what I've done so far:
Category.js (Model)
module.exports = {
connection: 'MongoDB',
attributes: {
name: {
type: 'string',
required: true,
unique: true
},
description: {
type: 'string'
},
products: {
collection: 'product',
via: 'category'
},
parentCategory: {
model: 'category'
},
subCategories: {
collection: 'category',
via: 'parentCategory'
},
addSubCategory: function(sc) {
this.subCategories.push(sc);
}
}
};
It doesnt seem to be working. I'm calling addSubCategory from my controller, sc and this values are correct, but it never adds the "subCategory" attribute to the category. I know this may not be the best approach, any suggestions?
You don't need subCategories attribute. Following design would be my suggestion.
module.exports = {
connection: 'MongoDB',
attributes: {
name: {
type: 'string',
required: true,
unique: true
},
type: {
type: 'string',
enum: ['parent', 'subcategory'],
},
description: {
type: 'string'
},
products: {
collection: 'product',
via: 'category'
},
parentCategory: {
model: 'category' // this exists only if type is 'subcategory' else null
},
addSubCategory: function(sc) {
this.subCategories.push(sc);
}
}
};
Let me know if you have any doubt.
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()
My model definition looks like this:
//api/models/Table.js
module.exports = {
tableName: 'table',
autoCreatedAt: false,
autoUpdatedAt: false,
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true,
size: 11
},
title1: {
type: 'string',
index: true,
size: 255
},
title2: {
type: 'string',
size: 255
},
title2: {
type: 'string',
size: 255
},
countries: { //Countries nationalities
model: 'hg_laender'
},
year: {
type: 'string',
size: 4
},
relased: { //released
type: 'string',
enum: ['true', 'false']
},
createdOn: { //Created on
type: 'datetime'
},
changedOn: { // Changed on
type: 'datetime'
},
documents: { //Document type
collection: 'documents',
via: 'table',
dominant: true
},
creator: { //Creator
collection: 'creator',
via: 'table',
dominant: true
},
kanton: { // Canton
collection: 'kanton',
via: 'table',
dominant: true
},
language: {
collection: 'language',
via: 'table',
dominant: true
}
}
};
The code generating the error is the following
Table.find()
.exec((err, tables) => {
if(err) {
sails.log.error('first error', err);
}
sails.log.debug(tables[0]); //The record is loaded correctly
tables[0].save((err, model) => {
if(err) {
sails.log.error('second error', err);
}
});
});
I get the following error message:
error: second error Error (E_UNKNOWN) :: Encountered an unexpected error
at new WLError (/home/xxx/node_modules/waterline/lib/waterline/error/WLError.js:25:15)
at /home/xxx/node_modules/waterline/lib/waterline/model/lib/defaultMethods/save.js:196:17
at /home/xxx/node_modules/async/lib/async.js:52:16
at /home/xxx/node_modules/async/lib/async.js:550:17
at /home/xxx/node_modules/async/lib/async.js:544:17
at _arrayEach (/home/xxx/node_modules/async/lib/async.js:85:13)
at Immediate.taskComplete (/home/xxx/node_modules/async/lib/async.js:543:13)
at processImmediate [as _immediateCallback] (timers.js:383:17)
If a use the create() method it works. t actually save the record on the database. But if I try to update it, it doesn't work.
Any idea of what I'm doing wrong?
Additional info:
- sails.js version: 0.12.8
Seems like there was a problem if a manually specify the id of the model.
Now i changed the model like below and it works. Btw I don't know why specifing the id will not work. Also it' doesn't throw any error when creating a model..
//api/models/Table.js
module.exports = {
tableName: 'table',
autoCreatedAt: false,
autoUpdatedAt: false,
attributes: {
//id: {
// type: 'integer',
// autoIncrement: true,
// primaryKey: true,
// size: 11
//},
title1: {
type: 'string',
index: true,
size: 255
},
title2: {
type: 'string',
size: 255
},
title2: {
type: 'string',
size: 255
},
countries: { //Countries nationalities
model: 'hg_laender'
},
year: {
type: 'string',
size: 4
},
relased: { //released
type: 'string',
enum: ['true', 'false']
},
createdOn: { //Created on
type: 'datetime'
},
changedOn: { // Changed on
type: 'datetime'
},
documents: { //Document type
collection: 'documents',
via: 'table',
dominant: true
},
creator: { //Creator
collection: 'creator',
via: 'table',
dominant: true
},
kanton: { // Canton
collection: 'kanton',
via: 'table',
dominant: true
},
language: {
collection: 'language',
via: 'table',
dominant: true
}
}
};
I too faced this Issue while using Sails with mongo. I fixed this by changing "id" attribute to some other attribute, say "Id". While creating a record, an "id" attribute is created itself that holds mongo ObjectId. May be this could be the reason for not allowing two id attribute at the same time resulting into error.
I have models Playlist.js and User.js. I want to have a list of users in Playlist who can answer for the comments on them. I do not want the attribute to appear in User. (i.e. one-way-association)
Playlist.js
module.exports = {
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey:
},
name: {
type: 'string',
size: 128,
required: true
},
// many to many relationship with role
roles_with_access: {
collection: 'role',
via: 'playlist',
through: 'rolehasplaylist'
},
// THIS ATTRIBUTE ASSOCIATE WITH ONE USER
// BUT INSTEAD OF THAT I WANT A LIST OF USERS
users_who_can_answer_comments: {
model: 'user'
}
}
};
User.js
module.exports = {
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true,
},
name: {
type: 'string',
size: 128,
required: true
},
email: {
type: 'email',
required: true,
unique: true
},
adminRole: {
model: 'role'
}
}
};
Sails documentation have mentioned one-way association only for one-to-one mapping - http://sailsjs.org/documentation/concepts/models-and-orm/associations/one-way-association
I want to find a way to have a list of users with associations to users?
Change model to collection:
users_who_can_answer_comments: {
collection: 'user'
}
I have an upsert query in mongoose which was working in 3.8 but, after I've upgraded to 4 I'm getting
Unable to invalidate a subdocument that has not been added to an array
this is my model:
var ActivitySchema = new Schema({
owner:{
type: Schema.Types.ObjectId,
ref: 'User'
},
sequence:{
type:Number,
default: 0
},
items:[
{
posted:{
type:Date,
default:Date.now
},
verb:{
type: String,
enum: [ 'leave','join','support','share','comment', 'upload', 'rate','message','update', 'signup']
},
text:{
type: String,
},
reference: {
objectType:{
type: String,
enum: [ 'document','element','process', 'project', 'user']
},
refObj:{}
}
}]
});
the upsert:
Activity.update({
$and:[
{'owner':ownerId},
{'sequence':bucket}
]},
{
$push:{items:newItem }
},
{
upsert:true
}).execAsync();
and the data is like this:
//newItem
{ verb: 'join',
text: 'Has joined to a team',
reference:
{
refObj: { teamId: '56269fd1e923cc7a7b46dcf8', name: 'test1' },
objectType: 'user'
}
}
ownerId is a mongoId like 56251c01507dc35423694118
and bucket is an integer 0
is there any breacking change that I need to be aware?, I've been looking and I haven't found yet related, any other workaround, solution?
I had encountered the same problem, if it is the same case then make sure all fields type are matched to the mongoose.model('yourModel').
Hopes that helps.
I'm trying to add a value to a nested schema:
groups = new SimpleSchema({
title: { type: String, optional: true },
element: { type: [elements], optional: true }
});
elements = new SimpleSchema({
description:{ type: String, optional: true },
anything: { type: String, optional: true }
});
MongoDB.attachSchema(new SimpleSchema({
title: { type: String },
slug: { type: String, unique: true },
language: { type: String, defaultValue: "en" },
group: { type: [groups], optional: true },
}));
Now I want to add just a new element-description to an existing entry in the DB. I tried this, but it doesn't work.
Uncaught Error: When the modifier option is true, validation object must have at least one operator
var newElement = {
description: 'insert this as a new element description'
};
MongoDB.update({ _id: Id }, { $push: { 'group.element': newElement }}, function(error) { if(error) console.warn(error); });
Is it correct to use 'group.element' as a $push-parameter?
Update
I forgot the index of group: $push: { 'group.0.element': newElement }
Also I have to define elements before groups in the schema.