js sequelize chain association accessors - javascript

I have three models: Url, Action, Container
I would like to get the Container of a Url through the following relations:
db.Url.belongsTo(db.Action, { foreignKey: 'action_id'});
db.Action.belongsTo(db.Container, { foreignKey: 'container_id'});
I was hoping for something like:
db.Url.findOne(...).getAction().getContainer()
However it only seems to work when I work with the entities one after another.
i.e. query the db for the url. Then call url.getAction() and then getContainer.
So it is three separate querys instead of one.

So you are asking for a nested include? I don't quite understand what you need to find, the Container through a given Url.id?? Anyaways you're looking for something like this
db.Url.find({
include: [
{
model: db.Action,
include : [{
model: db.Container
}]
}
]
})
.then(function(response) {
return res.json(response);
})
.catch(function (err) {
// more code...
});
This will a return a single json with all corresponding associations.

Related

Sequelize and defaultScope with Models associated

I am using Sequelize with Express, and Node js and I am trying to define defaultScope for Models.
Card and Tag have a Many To Many association.
Here are Models definitions and addScope
// Models Associations
// ONE TO MANY
List.hasMany(Card, {
as: "cards",
});
Card.belongsTo(List, {
as: "list",
});
// MANY TO MANY
Card.belongsToMany(Tag, {
as: "tags",
through: "card_has_tag",
updatedAt: false,
});
Tag.belongsToMany(Card, {
as: "cards",
through: "card_has_tag",
updatedAt: false,
});
// SCOPES
Card.addScope("defaultScope", {
include: {
association: "tags",
},
});
List.addScope("defaultScope", {
include: {
association: "cards",
include: "tags",
},
});
// What I would like to implement
// If I comment lines below => List and Card queries are working
Tag.addScope("defaultScope", {
include: {
association: "cards",
},
});
I would like to print by default all related infos with associated relations.
I want to get this info when I execute a sequelize query for each model.
LISTS with associated :
cards
tags
CARDS with associated:
tags
TAGS with associated :
cards
I manage to get 1 & 2, but when I add Tag.addScopenothing is working anymore.
When I change defaultScope by another string by defining a scope all (for example) , and when I use model.scope("all").findAll(), this is working, but it is not what I would like to do becaue I want to use defaultScope to have a default behavior so I don't have to specify scope in queries command like (findAll...)
Is there a way I can do that ?
The way you are trying to set it up results in an endless recursion, you simply can't have it like that.
If you set it up like that and query Card it will include Tag which will include Card which will include Tag and so on until you get Maximum call stack size exceeded.
There is a workaround you can use, which is to add another scope which includes nothing, then specify that scope for the model in the defaultScope.
Tag.addScope("noInclude", {});
Card.addScope("noInclude", {});
Tag.addScope("defaultScope", {
include: [
{
model: Card.scope("noInclude"),
as: "cards"
}
]
});
Card.addScope("defaultScope", {
include: [
{
model: Tag.scope("noInclude"),
as: "cards"
}
]
});
This should give you the desired behaviour.

SailsJs get list of objects population relationships

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

Sequelize: .createAssociation() or .setAssociation doesn't update the original object with created data

I've been stuck on this for a while. Take the following code as an example:
models.Summoner.findOne({
include: [{ model: models.RankedStats, as: 'SummonerRankedStats', required: true }],
where: { summonerId: summonerId, server: server }
}).then(function(summoner) {
models.RankedStats.create({
totalWins: 0,
totalLosses: 0
}).then(function(rankedStats) {
summoner.setSummonerRankedStats(rankedStats).then(function() {
console.log(summoner.SummonerRankedStats)
//This outputs undefined
summoner.getSummonerRankedStats().then(function(srs) {
console.log(srs)
//This outputs the RankedStats that were just created
})
models.Summoner.findOne({
include: [{ model: models.RankedStats, as: 'SummonerRankedStats', required: true }],
where: { summonerId: summonerId, server: server }
}).then(function(summoner) {
console.log(summoner.SummonerRankedStats)
//This outputs the SummonerRankedStats object
})
})
})
})
So, to put it simply... If I have a Summoner (var summoner) and perform a .setAssociation() or .createAssociation() on it, and then log summoner, the data created isn't there. If I fetch it again from the database (with .getAssociation() or by searching for that Summoner again) I can access it, but I was hoping to avoid that extra DB call.
Is there a way to add this information to the original object when using .create() or .set()? It can be achieved by doing something like:
summoner.dataValues.SummonerRankedStats = rankedStats
But that seems somewhat hacky :)
Is there a correct way to do it, or does it even make any sense?
Thanks in advance!

How bind search values in mongodb with mongoose

I have the following code in my /search/:query route:
var param = {
query: req.query['query']
}
MyModel.find({
"$or": [
{ 'name': req.param.query },
{ 'age': req.param.query },
{ 'event': req.param.query },
]
}, function (err, results) {
if (err) {
console.log(err)
}
else {
res.render('index', {
data: results
});
}
}
);
And is good, i can search for pretty much every data that i want, but only individually. What if i want search name + age, can i? Example: 'Leo 22'.
There is any way that mongoose help me with this?
UPDATE:
My problem is:
I have tables lists it titles, this title is the concatenation of 'eventName' and 'eventDate'.
Real examples of this fields:
'Special Event - 20/12/2015'
'Classic Event - 12/03/2015'
'Hot Summer Event - 05/07/2005'
Every week will be create 4 events. In some point, a user will search for an old event, and i believe that the user will search in this format:'EVENT NAME - EVENT DATE'..
So i need a way to bind this values in my controllers.
I'm no familiar with mongoose but in order to do that, you must have a way to bind your query param to the attribute you want to search. Otherwise, they wouldn't know Leo is name and 22 is age.
Ur path would be like search?name=:name&age=:age&event=:event and in your code, you will have to process like if the param is not null, add and condition to it.
It seems you are using only one parameter (req.param.query) to filter all attributes. That's not mongoose related: you could create distinct parameters for each attribute and pass them along the query string.
For instance:
"$or": [
{ 'name': req.param.name },
{ 'age': req.param.age },
{ 'event': req.param.event },
]
And your HTTP request will be like this:
http://youraddress/expressRoute?name=Leo&age=22

Publish a collections and other collection's documents which have relation with any document in the first collection

The scenario is that I want to publish one whole collection and users' data (such as profile) who have relation with any document in the the first collection.
The problem is how can I publish that part of users collections?
Well, there are two ways, first is using package
https://atmospherejs.com/cottz/publish-with-relations
And second one - in publish function you can return multiple cursors, from docs
Meteor.publish("roomAndMessages", function (roomId) {
check(roomId, String);
return [
Rooms.find({_id: roomId}, {fields: {secretInfo: 0}}),
Messages.find({roomId: roomId})
];
});
After some research, I found reywood:publish-composite solved my problem completly.
Example:
Meteor.publishComposite('getItemsList', {
find: function() {
return Items.find({});
},
children: [
{
find: function(item) {
return Meteor.users.find(
{ _id: item.userId },);
}
}
]});
This will publish all the items documents with any user document that have a relation with it. ( Items.userId is mapped to Meteor.users._id )

Categories

Resources