Sailsjs Update model Mongodb - mongodb

I have two collections; user and address. Address collection has association with user collection.
module.exports = {
attributes: {
email: {
type: 'email',
required: true,
unique: true
},
cart: {
collection: 'cart',
via: 'user'
},
isAdmin : {
type : 'boolean',
defaultsTo : false
},
}
module.exports = {
attributes: {
user: {
model: 'user',
required: true
},
address: {
type: 'string',
},
addressAdditional: {
type: 'string',
},
city: {
type: 'string',
},
state: {
type: 'json',
},
zip: {
type: 'string',
},
}
I have the userId and address info passed from the UI and I would like to update the address collection. I tried the following snippet but it does not seem like the data is getting updated.
var address = {
address: "123",
city: "Test City",
state: "NY",
zip: "12345"
};
User.findOne({user:userId}).then(function(model){
Address.update({id:model.id}, address)});
What am I doing wrong? Thanks

After looking in to the sails adapter.js javascript, a function called mongo.objectId to create an ObjectId.
var addressObjectId = mongo.objectId(model.id);
Address.update({_id:addressObjectId}, address)})
https://github.com/balderdashy/sails-mongo/blob/master/lib/adapter.js#L266

Related

Ordering two reference arrays together

Suppose I have the following schemas:
var QuizSchema = new mongoose.Schema({
name: { type: String, required: true },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
});
var QuestionSchema = new mongoose.Schema({
number: { type: String, required: true }, // e.g. 1, a, i, anything
question: { type: String, required: true },
type: { type: String, enum: ['multiple choice', 'multiple select', 'short answer'] },
choices: [String],
answers: [String]
});
var QuestionGroupSchema = new mongoose.Schema({
number: { type: String, required: true }, // e.g. 1, a, i, anything
prompt: { type: String },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});
I am trying to design a way that will allow me to order questions and question groups together.
I was thinking maybe of adding a new field order
var QuizSchema = new mongoose.Schema({
// ...
order: [
{
type: { type: String, enum: ['Question', 'QuestionGroup'] },
id: mongoose.Schema.Types.ObjectId // reference
}
]
});
such that in the database, the field would contain something such as
[
{ type: 'Question', id: ObjectId('57867a34567g67790') },
{ type: 'Question', id: ObjectId('57867a34567g67765') },
{ type: 'QuestionGroup', id: ObjectId('69864b64765y45645') },
{ type: 'Question', id: ObjectId('57867a34567g67770') },
{ type: 'QuestionGroup', id: ObjectId('69864b64767y45647') }
]
This may mean that I would need to "populate" the ordered list of questions and question groups as
quiz.populate('questions questionGroups').exec(function (err, quiz) {
// sort questions and groups by the order
quiz.order = quiz.order.map(function (o) {
if (o.type === 'QuestionGroup') {
return quiz.questionGroups.id(o.id);
}
return quiz.questions.id(o.id);
});
});
So my question: is there a better way to design this?
Virtuals can come in handy here; without persisting order field in db and doing calculations on client each time:
var QuizSchema = new mongoose.Schema({
name: { type: String, required: true },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
},
{
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
}
);
QuizSchema
.virtual('order')
.get(function() {
return this.questions.concat(this.questionGroups); //questions followed by questionGroups
});
Sort on createdAt is of course optional, but for that you need to have this field in Question and QuestionGroup:
Quiz.find({}, function (err, quiz) {
//...
})
.populate({path : 'questions', options: {sort: { 'createdAt': 1 }}})
.populate({path : 'questionGroups', options: {sort: { 'createdAt': 1 }}});

ReferenceError: user is not defined in user api

When I open localhost:1337/user I got Internal Server Error
Something isn't right here.
ReferenceError: user is not defined
How can I fix it? My API is not working. I can't insert data in database using html forms in sailsjs.
My user model is:
module.exports = {
attribute: {
firstname: {
type: 'string',
unique: true
},
lastname: {
type: 'string',
unique: true
},
organisationName: {
type: 'string',
unique: true
},
DepatmentName: {
type: 'string',
unique: true
},
DOB: {
type: 'date',
unique: true
},
DOJ: {
type: 'date',
},
DOL: {
type: 'date',
},
Address: {
type: 'string',
},
City: {
type: 'string',
},
State: {
type: 'string',
},
Country: {
type: 'string',
},
email: {
type: 'string',
email: true,
required: true,
unique: true
},
encryptedPassword: {
type: 'string',
},
ContactNumber: {
type: 'integer',
},
//toJSON: function() {
// var obj = this.toObject();
//
// }
}
};
You are calling a variable "user" and it doesn't exist or it's empty. Check youre code for this variable..
In youre usermodel, you only have firstname and lastname. I guess you need one of this. If you want more specific help, then you have to show us some extra coding of the page, not only the model.

Can I use primary key in association for find Waterline

I've created two models with associations:
User.js
attributes: {
fullname: {
type: 'string',
required: true
},
username: {
type: 'string',
unique: true,
required: true
},
email: {
type: 'email',
unique: true,
required: true
},
mothertongue: {
type: 'string'
},
passports: {
collection: 'Passport',
via: 'user'
},
words: {
collection: 'Words',
via: 'owners',
dominant: true
}
}
Words.js
attributes: {
word: {
type: 'string',
unique: true,
required: true
},
language: {
type: 'string',
required: true
},
owners: {
collection: 'User',
via: 'words'
}
}
When I'm searching about words owner someone he return back empty array
Words
.find({
owners: req.session.passport.user
})
.exec(function(err, data){
if (err) {
return res.send('error');
}
res.send(data);
})
Also I used .populate('owners') but don't work too.
To find the words a user has:
User.find(1).populate('words')
To find which users own a particular word, use
Word.find(id).populate('owners', {id : ...})

Mongoose not populating previously saved document with reference to newly saved document

all.
I am writing a MEAN stack application, using Mongoose (4.0.6) with Node/Express to interface with MongoDB, and I am running into difficulty populating saved documents when I later save new documents that the existing document should have a reference to. Specifically, in the app I have a user create an instance of a company before creating their admin account for that company, so when the user registers him/herself as an admin, I'd like the company document to populate its users array with the new user.
Here are my schemas for company and user:
User.js...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var userSchema = new Schema({
first_name: { type: String, required: '{PATH} is required!' },
last_name: { type: String, required: '{PATH} is required!' },
username: { type: String, required: '{PATH} is required!', lowercase: true, unique: true },
password: { type: String, required: '{PATH} is required!' },
roles: { type: [String] },
company: { type: ObjectId, ref: 'Company', required: true },
db_permissions: [{ type: ObjectId, ref: 'DataConnection' }],
created_by: { type: ObjectId, ref: 'User' },
created_at: { type: Date, default: Date.now },
updated_at: [{ type: Date, default: Date.now }]
});
var User = mongoose.model('User', userSchema);
module.exports = {
User: User
};
Company.js...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var companySchema = new Schema({
name: { type: String, uppercase: true, required: '{PATH} is required!', unique: true },
industry: { type: String, required: '{PATH} is required!' },
phone: { type: String, required: '{PATH} is required!' },
address_line_1: { type: String, uppercase: true, required: '{PATH} is required!' },
address_line_2: { type: String, uppercase: true },
city: { type: String, uppercase: true, required: '{PATH} is required!' },
state_prov: { type: String, uppercase: true, required: '{PATH} is required!' },
postal_code: { type: String, required: '{PATH} is required!' },
country: { type: String, required: '{PATH} is required!' },
logo_url: String,
users: [{ type: ObjectId, ref: 'User' }],
data_connections: [{ type: ObjectId, ref: 'DataConnection' }],
created_at: { type: Date, default: Date.now },
updated_at: [{ type: Date, default: Date.now }]
});
var Company = mongoose.model('Company', companySchema);
module.exports = {
Company: Company
};
Here is the code in my controller:
User.create(userData, function(err, user) {
if(err) {
if(err.toString().indexOf('E11000') > -1) {
err = new Error('Duplicate email');
}
res.status(400);
return res.send({ reason:err.toString() });
}
console.log('company id: ' + user.company);
Company.findById(user.company)
.populate({path: 'users'})
.exec(function (err, company) {
if (err) return handleError(err);
console.log(company.name + '\'s users now includes ' + company.users);
});
res.send(user);
The company (e.g. TEST53) saves to the database correctly with an empty users array:
{
"_id": "55ae421bf469f1b97bb52d5a",
"name": "TEST53",
"industry": "Construction",
"phone": "2352626254",
"city": "GDFGD",
"country": "United States",
"address_line_1": "DSGDFGH",
"state_prov": "GF",
"postal_code": "45645",
"logo_url": "",
"__v": 0,
"updated_at": [
"2015-07-21T12:59:07.609Z"
],
"created_at": "2015-07-21T12:59:07.597Z",
"data_connections": [],
"users": []
}
Then when I create the user, it saves correctly:
{
"_id": "55ae4238f469f1b97bb52d5b",
"username": "test53#test.com",
"password": "$2a$12$ZB6L1NCZEhLfjs99yUUNNOQEknyQmX6nP2BxBvo1uZGlvk9LlKGFu",
"company": "55ae421bf469f1b97bb52d5a",
"first_name": "Test53",
"last_name": "Admin",
"__v": 0,
"updated_at": [
"2015-07-21T12:59:36.925Z"
],
"created_at": "2015-07-21T12:59:36.550Z",
"db_permissions": [],
"roles": [
"admin"
]
}
And I can see that the correct ObjectId prints to the console for user.company:
company id: 55ae421bf469f1b97bb52d5a
But the company's users array doesn't populate with the user's id, and the console.log inside the .exec function prints 'TEST53's users now includes '.
I have tried several ways of wiring this up, with just 'users' instead of { path: 'users' }, writing a function that pushes the user into the array, using .run instead of .exec, but so far without success.
Is there something obvious I'm missing? Thanks in advance for any suggestions!
You're not actually adding the user to the company.
Try this:
Company.findById(user.company, function (err, company) {
if (err) return handleError(err);
// Add the user to the company's list of users.
company.users.push(user);
// Need to save again.
company.save(function(err) {
if (err) return handleError(err);
console.log(company.name + '\'s users now includes ' + company.users);
});
});
res.send(user);
It seems to me that all you want to do is to update the Company model to add the user, as opposed to actually use the (populated) Company document as a response, so I left out an additional Company.findById(...).populate(...) call.

sails.js One to many associations -- TypeError: Cannot convert null to object

I am getting this strange error recently. It was not there earlier and I don't remember changing much.
error: Error (E_UNKNOWN) :: Encountered an unexpected error
TypeError: Cannot convert null to object
at hasOwnProperty (native)
at utils.object.hasOwnProperty (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/lib/utils.js:28:14)
at /home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/where.js:259:11
at Array.forEach (native)
at WhereBuilder.complex (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/where.js:177:36)
at complexWhere (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/index.js:244:16)
at find (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/index.js:85:23)
at Cursor.populateBuffers [as $populateBuffers] (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/lib/adapter.js:539:31)
at Cursor.run (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-cursor/cursor/cursor.js:45:8)
at runJoins (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-cursor/index.js:51:10)
Details: TypeError: Cannot convert null to object
The error goes away when I remove the one to many association from user model. Here are the models for reference:
Underlying database is postgres
User.js
module.exports = {
tableName: "users",
attributes: {
name: {
type: "string",
required: false
},
permission: {
type: "integer",
defaultsTo: 2
},
primary_phone: {
model: "phone",
required: true
},
phone: {
collection: "phone",
via: "id"
},
primary_email: {
model: "email",
required: true
},
email: {
collection: "email",
via: "id"
}
}
};
Phone.js
module.exports = {
attributes: {
number: {
type: "string",
required: true
},
owner: {
model: "user"
}
}
};
Email.js
module.exports = {
attributes: {
email: {
type: "email",
required: true
},
owner: {
model: "user"
},
verified: {
type: "boolean",
defaultsTo: false
}
}
};
I don't think you can do via: "id" - the id field doesn't refer back to the User model. You should create a new attribute for both the Email and Phone model and link those back to the User model.
For example,
User.js:
...
phone: {
collection: "phone",
via: "nonPrimaryPhoneOwner"
},
email: {
collection: "email",
via: "nonPrimaryEmailOwner"
}
...
Email.js:
...
nonPrimaryEmailOwner: {
model: "user"
}
...
Phone.js:
...
nonPrimaryPhoneOwner: {
model: "user"
}
...