我有一个像这样的用户模型:
/**
* User.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
firstName: 'string',
lastName: 'string',
fullName: {
type: 'string',
index: true
},
loginMethod: 'integer',
emailAddress: {
type: 'string',
unique: true
},
password: 'string',
friends: {
collection: 'User'
},
tallys: {
collection: 'Tally',
via: 'associatedUser'
},
friendsTallys: {
collection: 'Tally',
via: 'invitedUsers'
},
toJson: function() {
var obj = this.toObject();
delete obj.friends;
delete obj.tallys;
delete obj.friendsTallys;
return obj;
}
},
beforeCreate: function(values, cb) {
// Set the full name property using the first name and the last name
values.fullName = values.firstName + " " + values.lastName;
cb();
}
};
我有一个像这样的Tally模型:
/**
* Tally.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
associatedUser: {
model: 'User'
},
type: 'integer',
yesThisCount: 'integer',
noThatCount: 'integer',
caption: 'string',
photos: {
collection: 'Photo'
},
invitedUsers: {
collection: 'User'
}
}
};
我有一个像这样的bootstrap js文件:
/**
* Bootstrap
* (sails.config.bootstrap)
*
* An asynchronous bootstrap function that runs before your Sails app gets lifted.
* This gives you an opportunity to set up your data model, run jobs, or perform some special logic.
*
* For more information on bootstrapping your app, check out:
* http://sailsjs.org/#/documentation/reference/sails.config/sails.config.bootstrap.html
*/
var async = require('async');
module.exports.bootstrap = function(cb) {
// It's very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
/**
* Make some fake users for testing
* These will not be used for logging in.
* This is just to check addFriend and searching
*/
var asyncCreateUsers = [];
var asyncCreatePhotos = [];
var asyncCreateTallys = [];
var usersJS = [];
var usersSails = [];
var talliesJS = [];
var yesNoPhotoSails;
var thisPhotoSails;
var thatPhotoSails;
// create the user javascript objects
for (idx = 0; idx < 5; idx ++) {
usersJS.push({
firstName: 'Test0' + idx + '_first',
lastName: 'Test0' + idx + '_last',
emailAddress: 'test0' + idx + '@test.com',
password: 'testing',
loginMethod: 0
});
}
// push each thing into the asyncTasks array
_.each(usersJS, function(user) {
asyncCreateUsers.push(function(callback){
User.create(user).exec(function(error, user){
if (error) {
sails.log.error("whoops, user not created");
} else {
sails.log.info("user created");
usersSails.push(user);
}
callback();
}
);
});
});
async.parallel(asyncCreateUsers, function() {
// Finish created users in sails
sails.log.info('created users, now create photos');
// Make them all friends.
createPhotosAsynchronously();
});
function createPhotosAsynchronously() {
// Create my photos
var yesNoPhoto = {
path: 'https://upload.wikimedia.org/wikipedia/en/6/6f/Yoda_Attack_of_the_Clones.png'
};
var thisPhoto = {
path: 'http://static.comicvine.com/uploads/original/11118/111184078/4610796-0849145928-4-Ana.jpg'
};
var thatPhoto = {
path: 'http://s3.amazonaws.com/rapgenius/1345598281_Episode_4_Luke_Skywalker_1.jpg'
};
asyncCreatePhotos.push(function(callback){
Photo.create(yesNoPhoto).exec(function(error, photo){
if (error) {
sails.log.error('whoops, yesno photo not created');
} else {
yesNoPhotoSails = photo;
}
callback();
});
});
asyncCreatePhotos.push(function(callback){
Photo.create(thisPhoto).exec(function(error, photo){
if (error) {
sails.log.error('whoops, this photo not created');
} else {
thisPhotoSails = photo;
}
callback();
});
});
asyncCreatePhotos.push(function(callback){
Photo.create(thatPhoto).exec(function(error, photo){
if (error) {
sails.log.error('whoops, that photo not created');
} else {
thatPhotoSails = photo;
}
callback();
});
});
async.parallel(asyncCreatePhotos, function(){
// Finished creating photos, create tallys now.
sails.log.info('created photos, now create tallys');
createTallysAsynchronously();
});
}
function createTallysAsynchronously() {
var userIds = _.pluck(usersSails.slice(), 'id');
// create the tallies javascript objects
for (idx = 0; idx < usersSails.length; idx ++) {
talliesJS.push({
associatedUser: usersSails[idx],
type: 0,
yesThisCount: 0,
noThatCount: 0,
caption: 'YesNo',
photos: [yesNoPhotoSails]
});
talliesJS.push({
associatedUser: usersSails[idx],
type: 1,
yesThisCount: 0,
noThatCount: 0,
caption: 'ThisThat',
photos: [thisPhotoSails, thatPhotoSails]
});
}
_.each(talliesJS, function(tally) {
asyncCreateTallys.push(function(callback){
Tally.create(tally).exec(function(error, createdTally){
if (error) {
sails.log.error("tally did not create");
} else {
Tally.findOne({id: createdTally.id}).populate('invitedUsers').exec(
function(e,r){
var associatedUser = r.associatedUser;
sails.log.info('associated User: ' + associatedUser);
var ids = _.reject(userIds, function(id) {return id == associatedUser});
_.each(ids, function(id){
r.invitedUsers.add(id);
r.save(function(err){sails.log.info('saved after adding invitedUser: ' + id)});
});
callback();
});
}
});
});
});
async.parallel(asyncCreateTallys, function() {
// FIN
sails.log.info('created tallys, finished');
cb();
});
}
};
我有一个登录方法,如下所示:
var loginUserFunction = function(){
User.findOne({emailAddress: user.emailAddress})
.populate("tallys")
.populate('friendsTallys')
.populate('friends')
.exec(function(err, found) {
if(err) {
sails.log.error("There was an error looking for the user: " + JSON.stringify(err));
return res.serverError({error: sails.config.errors.SERVER_ERROR});
}
if(found == null) {
sails.log.info("Could not find user with email address: " + user.emailAddress);
return res.badRequest({error: sails.config.errors.INVALID_EMAIL});
}
if(found && found.loginMethod != user.loginMethod)
{
sails.log.info("The user tried to login using the wrong method!");
return res.badRequest({error: sails.config.errors.INVALID_LOGIN_METHOD});
}
var friends = found.friends;
var friendsTallysIds = _.pluck(found.friendsTallys, 'id');
// We populated tallys and friendsTallys but we need to get the fields in those tallys to be populated so we have to query directly for the Tallys
Tally.find(_.pluck(found.tallys, 'id'))
.populate('associatedUser')
.populate('invitedUsers')
.populate('photos')
.exec(function(err, tallys) {
if(err){
sails.log.error("There was an error getting the tallys for the user: " + JSON.stringify(err));
return res.serverError({error: sails.config.errors.SERVER_ERROR});
}
if(tallys == null)
{
tallys = [];
}
Tally.find(_.pluck(found.friendsTallys, 'id'))
.populate('associatedUser')
.populate('invitedUsers')
.populate('photos')
.exec(function(err, friendsTallys) {
if(err){
sails.log.error("There was an error getting the friends' tallys for the user: " + JSON.stringify(err));
return res.serverError({error: sails.config.errors.SERVER_ERROR});
}
if(friendsTallys == null)
{
friendsTallys = [];
}
sails.log.info("The user was found: " + user.emailAddress);
// Generate an auth token for the user
var userAuthToken = EncryptionService.generateUserAuthToken(found);
// Set the token in the response headers
res.set('userAuthToken', userAuthToken);
// Remove the tallys, friendTallys, friends from the found object
// Subscribe the user to this own model
User.subscribe(req.socket, found);
// Subscribe to own tallys
Tally.subscribe(req.socket, tallys);
// Subscribe to Friends' Tallys
Tally.subscribe(req.socket, friendsTallys);
// Send the response
res.json({
user: found,
tallys: tallys,
friendsTallys: friendsTallys,
friends: friends
});
});
});
});
}
我的问题是我的用户对象中的friendsTallys字段只显示了2个标记,实际上应该有8个标记,因为我为每个用户创建了2个标记,然后为每个标记邀请所有其他用户。此外,在Tallys领域,在friendsTalls中的那两个标记是相同的标记。这是我断点的一个视图:
感谢您的帮助。如果您需要更多信息/代码/上下文,请告诉我。