Sequelize where on many-to-many join - javascript

I am hoping somebody can help me. I am using the Sequelize ORM for express.js and I have a working many-to-many relationship between 2 tables.
For the sake of simplifying my query lets pretend my tables are Users, Books and UserBooks where UserBooks has UserId, BookId and an additional column (Lets say its NoOfTimesRead).
What I want to do is something like:
user.getBooks({
where: {
"userBooks.NoOfTimesRead": 0
}
});
If I type:
user.getBooks();
This works and returns all books, I just haven't been able to figure out how to query this by the additional column on the joining table.
I hope this makes sense,
Thanks for taking a look!

With Belongs-To-Many you can query based on through relation and
select specific attributes. For example using findAll with through
User.findAll({
include: [{
model: Project,
through: {
attributes: ['createdAt', 'startedAt', 'finishedAt']
where: {completed: true}
}
}]
});
Basically you can use through option and include the relationship that you linked. More can be found here

Related

How to get all the data from tables using TypeORM?

I'm building a Nest.js app with PostgresQL using TypeORM, I have entity User and entity Role, which are connected to each other with Many-to-Many relation. User has an array of roles, where each role assigned to this user is stored, but when I try to get all the users, that roles array doesn't show. Using Sequelize ORM i could get all the data from users using that
code - {include: {all: true}}, example:
const users = await this.usersRepository.find({include: {all: true}})
But in TypeORM it doesn't work. I tried to find it in TypeORM docs, but I didn't find an answer.
Sorry for my english, i hope you understood me.
It seems TypeORM wait for a list of relations you want to populate : https://orkhan.gitbook.io/typeorm/docs/relational-query-builder
In your case, it could look like :
const users = await this.usersRepository.find({relations: {roles: true}})

Sequelize Many-to-many querying model

Have some troubles with querying data.
Have 2 models with many to many relationships.
1st - S3FileData, 2nd - Playlists, they are connected through PlaylistContent table.
Also S3FileData is connected with User with User has-many playlists.
I need to query S3Files which belongs to user, but are not presented in user playlist.
I have playlist Id,userId.
Also I need offset and limit methods, so I tried to query this using findAndCountAll
But got no luck with it.
Would be very appreciate for any help :)
You will require include(joins in SQL) that will connect all these tables.
Something like this but first you will need to intertwine your models(db tables) which will look something like this:
User.belongsToMany(Profile, { through: Grant });
Profile.belongsToMany(User, { through: Grant });
User.hasMany(Grant);
Grant.belongsTo(User);
Profile.hasMany(Grant);
Grant.belongsTo(Profile);
Reference:
https://sequelize.org/master/manual/advanced-many-to-many.html
Now, Once you are through the joins you'll require to use those joins using include keyword in your findAll (or findAllAndCount as per the requirement):
Some basic code (You will need to try and tweak accordingly, this is rough code):
S3Files.findAll({
include: [
{
model: user,
attributes: ['some columns']
include: {
model: userPlaylist,
attributes: ['some columns'],
required: false
},
where: {[Op.and]: Sequelize.where(Sequelize.col('userPlaylist.userId'), 'is not' null)},
attributes: ['some columns']
]
});
lastly for offset and limit you'll require basic SQL logic of LIMIT and OFFSET
sample snippet from official docs for offset and limit:
Project
.findAndCountAll({
where: {
title: {
[Op.like]: 'foo%'
}
},
offset: 10,
limit: 2
})
Reference for the same:
https://sequelize.org/v5/manual/models-usage.html

Waterline: Find by value in JSON

I have a nested address attribute in one of my models.
attributes: {
address: {
type: 'json'
}
}
How can I find model instances located i.e. the same city.
I tried several queries:
Model.find({ "address.city": city })
Model.find({ address: { contains: city }})
But none seem to work for. Any ideas on how to properly formulate this query?
For sure, a mongo native call powered by Warerline works: https://sailsjs.com/documentation/reference/waterline-orm/models/native
Then the query object in your first attempt should work. Beware that then the mongodb documentation is the leading over the waterline one regarding query parameters. E.g. you need to cast ObjectId on id queries before using them in a native query.

Where clause on mongoose populate

in a Node.js App, i use this code to fetch some data:
Users.find({user_enabled:true}).populate('books')...
but right now i have a problem. i just want users with books that are in english language.
right now i'm doing this: fetch all users and all books for them. then in a loop, i can check each book language.. this is not a good solution. i need something like Where clause in SQL. if a user don't have a book in english language, i don't need that user in the result. Mongodb/mongoose cant do this? j have to use a code after fetching all results for this?
i need something like this:
Users.find({user_enabled:true}).populate('books').where({'books.language':'en'})
You can do this with match:
Users
.find({ user_enabled: true })
.populate({
path: 'books',
match: { 'language': 'en' },
})
.exec()
For more details check http://mongoosejs.com/docs/populate.html

Sails.js Waterline query by association

I'm developing and app with Sails.js and using Waterline orm for db. I'm developing functionality for users to do friend requests and other similar requests to each other. I have following URequest model for that:
module.exports = {
attributes: {
owner: {
model: 'Person'
},
people: {
collection: 'Person'
},
answers: {
collection: 'URequestAnswer'
},
action: {
type: 'json' //TODO: Consider alternative more schema consistent approach.
}
}
};
Basically owner is association to Person who made the request and people is one-to-many association to all Persons who the request is directed. So far fine.
Now I want to have a controller which returns all requests where certain user is involved in meaning all requests where user is either in owner field or in people. How I do query like "give me all rows where there is association to person P" ? In other words how I ca know which URequest models have association to a certain Person?
I tried something like this:
getRequests: function (req, res) {
var personId = req.param('personId');
URequest.find().where({
or: [
{people: [personId]}, //TODO: This is not correct
{owner: personId}
]
}).populateAll().then(function(results) {
res.json(results);
});
},
So I know how to do the "or" part but how do I check if the personId is in people? I know I should somehow be able to look into join-table but I have no idea how and couldn't find much from Waterline docs relating to my situation. Also, I'm trying to keep this db-agnostic, though atm I'm using MongoDB but might use Postgres later.
I have to be honest this is a tricky one, and, as far as I know what you are trying to do is not possible using Waterline so your options are to write a native query using query( ) if you are using a sql based adapter or native otherwise, or try doing some manual filtering. Manual filtering would depend on how large of a dataset you are dealing with.
My mind immediately goes to reworking your data model a bit, maybe instead of a collection you have a table that stores associations. Something like this:
module.exports = {
attributes: {
owner: {
model: 'URequest'
},
person: {
model: 'Person'
}
}
Using the sailsjs model methods (like beforeCreate) you could auto create these associations as needed.
Good Luck, I hope you get it working!

Categories