I am trying to get all of my posts' comments which comments count is greater than 0. I am tying to add the where in find and populate, but none of it worked.
Post model:
module.exports = {
attributes: {
user: {
model: 'user'
},
comments: {
collection: 'comment',
via: 'post'
}
};
PostController:
Post
.find({comments: {'>': 0}, user: me})
.populate('comments')
.exec(function(err, comments){
res.json(comments);
});
In current Sails/Waterline relations implementation you can't filter by one-to-many related fields. You need to filter the result after find is completed.
Related
I'm trying to get all users from a m:n association who is not a member of a specific group.
After a couple hours of trying and searching for something related this is what I came up with. But it doesn't solve my problem 100%
router.get('/:group_id/notmembers', function(req, res) {
models.User.findAll({
include: [
{ model: models.Group,
through: {
model: models.User_Group,
where: {
GroupId: {[Op.notIn] : [req.params.group_id] },
},
},
required: true,
}
],
}).then(function(groups) {
res.send(groups);
});
});
The code I've written so far returns all users who are part of another group instead of the specific group_id, this would work in a scenario where a user could only be member of one group. In my scenario users can be a member of multiple groups, therefore this doesn't work for me.
any help appreciated!
edit:
No one knows?
After blood sweat and tears I finally figured it out.
by setting the required variable to false I can include all db entries for the specific group_id, even if the users don't have it. From there I just select all entries where there is not a Group.id leaving only the users who aren't part of that specific group left.
router.get('/:group_id/notmembers', function(req, res) {
models.User.findAll({
include: [
{ model: models.Group,
through: {
model: models.User_Group,
where: {
GroupId: req.params.group_id,
},
},
required: false,
}
],
where: {
'$Groups.id$' : null,
}
}).then(function(groups) {
res.send(groups);
});
});
I have a model Post:
// Post.js
attributes:{
name: {type:"string"},
users: { collection: 'user', via: 'postsReceived' },
category: { model: 'category' },
// Plus lots of other fields and relationships to other models for example category, topic, etc...
}
And I have a model Users:
// Users.js
attributes:{
name: {type:"string"},
postsReceived: { collection: 'post', via: 'users', dominant: true }
}
A post can be sent to many users and a user may have many posts. This if fine however when it comes to populating a list of posts that a user is attached to this becomes quite difficult. I am using the below code to get the list of posts, however this does not populate the posts relationships. For example the below will only return a id for the category of the post. What is the best way (in terms of performance) to get this to work?
User.findOne({id:id})
.populate('postsReceived')
.exec(function(err, user){
if(err) return res.serverError(err);
if (user){
var result = user.postsReceived;
return res.json(result);
}
});
I found a solution for this that seems to work quite nicely from:
This Answer
The answer in the question above suggets using sails-hook-orm-offshore
Hey all just getting started with Sails js and mongoDB and im a bit confused.
I have two models with a many-to-many relationship:
User.js
module.exports = {
attributes: {
username: 'STRING',
password: 'STRING',
doors:{
collection: 'door',
via: 'users',
}
}
};
and Door.js
module.exports = {
attributes: {
name: 'STRING',
users:{
collection: 'user',
via: 'doors'
}
}
};
This works fine, I can create a user and a door and associate one with the other. However I'd like to have another field in the join, an expiry date (Say the user can only have access to a particular door until a particular date).
How would I go about doing that?
You need to create a many to many through association. However they are not officially supported as of yet.
You can manually do this however.
Now, in this example it may sometimes be a a little more difficult to get all the doors for a user and vice versa, because you have to preform a second look up. However you can do the following with this setup:
UserDoors
.find()
.where({expires:{'<':new Date()}})
.populate('doors')
.populate('users')
.exec(/*....*/)
Your models
User.js
module.exports = {
attributes: {
username: 'STRING',
password: 'STRING',
doors:{
collection: 'userDoors',
via: 'users',
}
}
};
userDoors.js
module.exports = {
attributes: {
doors:{
model: 'door'
},
users:{
model: 'user'
},
expires: 'datetime'
}
};
and Door.js
module.exports = {
attributes: {
name: 'STRING',
users:{
collection: 'userDoors',
via: 'doors'
}
}
};
Do a google search for sails.js many to many through to also help you find what your looking for.
I have this existing document in a collection Article in MongoDB database:
[ { site: 'www.atlantico.fr',
date: '2014-05-27T11:10:19.000Z',
link: 'http://www.atlantico.fr/example.html',
_id: 538473817eb00f082f4803fc,
__v: 0} ]
I want to add a new field day with value 'example' to this document, using Mongoose in Node.js. So I do:
Article.update(
{ link: 'http://www.atlantico.fr/example.html'},
{ $set : {day : 'example'} },
function(err){
});
But it does not work because when I query the document after that, no new field day appears...
I must have made a mistake when using update or $set in Mongoose, but I cannot find exactly my mistake.
What am I missing? Thanks!
try
Article.update(
{link: 'http://www.atlantico.fr/example.html'},
{day : 'example' },
{multi:true},
function(err, numberAffected){
});
and don't forget to add day to schema.
await Users.updateOne( {link: 'http://www.atlantico.fr/example.html'},{ $set: { day : 'example'} }, { multi: true });
update is deprecated
use await for db operation
if you want to add new filed in collection ,first check it is added in Model or not
(if you don't wan't use that filed as mandatory make is as "required: false")
Article.findByIdAndUpdate(id, { $set: { day: 'example' }}, { new: true }, function (err, article) {
if (err) return handleError(err);
res.send(article);
});
I prefer this way because it's contains a callback function.
reference and more info: http://mongoosejs.com/docs/documents.html
I have 3 models. User, Profile and comments.
Profile is an association of User (one to one) and comments are an association of Profile (one to many).
User Model:
attributes: {
profile: {
model: 'Profile'
},
}
Profile Model:
attributes: {
comments: {
collection: 'profileComment',
via: 'profile'
}
}
Comments model:
attributes: {
profile: {
model: 'Profile'
},
}
Getting the user profile works fine:
User.findOneById(id)
.populate('profile')
.exec(function (err, user) {
// user.profile
});
But then how would I populate the profile with the comments?
It seems like you could back into what you want by setting a user attribute on profile:
attributes: {
comments: {
collection: 'profileComment',
via: 'profile'
},
user: {
model: 'User'
}
}
And then querying with:
Profile.findOne({user: userId})
.populate('user')
.populate('comments')
.exec(function(err, profile) {
// use profile.user and profile.comments
});
Keep in mind, however, that Waterline doesn't currently implement true one-to-one associations, so if you set a Profile instance's user attribute to 123, the corresponding User instance won't automatically have its profile attribute set. This may not be a big deal--you can always look up Profile and populate User, like in the example above--but it's something to keep in mind.
Your other option is to keep things as they are and do a mapping, as in this question and answer.