NodeJS: Nested SQL query for custom REST API endpoint - mysql

I am creating a REST-API via NodeJS at the moment.
I created a MySQL database with these two tables:
table: physiotherapist = {(physio_id),(surname),(lastname),(appuser_id)}
--> PK = (physio_id)
--> FK = (appuser_id) and points on the PK of the second table
table: app_user = {(user_id),(username),(password)}
--> PK = (user_id)
For the REST-API endpoint I need the data of both tables.
For example, when I want the information of user with the id=3 and the api-enpoint is like 'localhost:3306/appusers/3' I want the data of both tables as a result.
This is what I got at the moment:
getUserById:function(id, callback) {
return db.query("Select * from user_physiO_app where user_id=?", [id], callback);
it'S only the data from the first table, so how do I get the data of the second table?
Thanks in regard!

Solved after the friendly advice of #Evert: I used the INNER JOIN syntax.
getUserById:function(id, callback) {
return db.query("Select * from user_physiO_app inner join physiotherapeut on
user_physiO_app.user_id = physiotherapeut.physiO_user_id where user_id=?", [id], callback);
}

Related

How to update multiple table at once using TypeORM

I'm using TypeORM with NestJS and I want to do this query to a MySQL DB:
UPDATE user u, table2 t2
SET u.is_active = 0, t2.is_active = 0
WHERE u.id = 'id'
AND t2.user_id = u.id;
Relations are:
User:
#OneToMany(
() => Table2,
(t2) => t2.user,
{
onDelete: 'CASCADE',
eager: true
}
)
field_table_2: Table2[]
And Table2
#ManyToOne(
() => User,
(user) => user.field_table_2
)
#JoinColumn({name:'user_id'})
user: User
The point is: One user can have many table2 but every row in table2 depends for only one user. Then a relation one-to-many and many-to-one. All right so far.
When I delete one user, I don't want remove the data into DB, I want to set field is_active to false in both tables.
I can do it in a single query using SQL but using TypeORM I've only found a solution using raw sql:
async remove(id: string) {
return await this.dataSource.query(`
UPDATE user u, table2 t2
SET u.is_active = 0, t2.is_active = 0
WHERE u.id = ?
AND t2.user_id = u.id`,[id])
}
But having an ORM I don't like to use raw SQL... how can I get the query I want using the ORM?
I know I can create a transaction, update first one table, then the other table and if everything is ok commit the transaction.
But, if I can do it in a single query, is efficient to do it in a transaction? I refer also for simplicity in a single query.
Thanks in advance.
TypeORM does not currently have an expressive way of updating multiple tables in a single query this via either query builder or repository methods. Currently those are limited to updating a single table.
I would say in your case, if you wish to do this in a single query pull out isActive into an entity / table of its own. Then both user and table 2 could have a 1-1 relationship with this new entity. Therefore, you only need to update one table entry.
Otherwise, this can be done with two separate update queries and a transaction. How you will perform the update is more a matter of choice, could use Repository or QueryBuilder.
There are also several options for managing transactions, the most fine grained of which is QueryRunner.
Pseudocode might look something like this:
queryRunner.startTransaction();
try {
await queryRunner
.createQueryBuilder()
.update(EntityA)
.set({isActive: false})
.execute();
await queryRunner
.createQueryBuilder()
.update(EntityB)
.set({isActive: false})
.execute();
await queryRunner.commitTransaction();
}
catch (e) {
queryRunner.rollbackTransaction()
}
However, I suspect that this could all also be done using CASCADE and softDelete

Eloquent nested relationship

i have a question to my db query.
My DB tables/schema:
customers_users (customer_id, user_id) relationship table
projects (project_id, customer_id, [.......]) belongs to customers
i try to get all Projects where a user has access through customers to, with the following query:
//call
User::find(Auth::id())->first()->projects();
//User.model
public function projects() {
return User::with('customers.projects')->get();
}
It works. But now i have User data, Customer data and Project Data in the result array. I want only the Projects. Is there an other way?
$user = auth()->user()->load('customers.projects');
$projects = $user->customers->pluck('projects')->collapse()->unique();

Building an entity join LINQ query

I have the following table strutucture and am accessing them by using MySQL Entity Framework:
Table Users
- Id
- Name
Table Subscriptions
- Id
- Id_User
- Id_Course
Table Courses
- Id
- Name
What I would like and am having a hard time to do so is building a link query for all users that returns a list with each entry containing:
User Id;
User name;
Concat string separated by comma with all courses for the user or 'no courses' string if none.
This list should be filtered by a part of users name.
I've started to build the code but can't finish it:
var Model db = new Model();
var list = from user in db.Users
join ???
where user.Name.Contains(filter.Trim())
select new { Name = user.Name, Id = user.Id, ???}
Can anyone help me please ?
You should use navigation properties (like User.Subscriptions) for this. Depending on how you created the model they may already be there, else you first should add them.
var query = from u in db.Users
where user.Name.Contains(filter) // trim the filter value first
select new
{
u.Name,
u.Id,
Courses = u.Subscriptions.Select(s => s.Course.Name)
};
var result = query.AsEnumerable()
.Select(q => new
{
q.Name,
q.Id
Courses = string.Join(", ", q.Courses)
};
The reason for doing this in two phases is that string.Join can't directly be used in an EF LINQ expression (can't be turned into SQL) so it must be done in memory (i.e. after an AsEnumerable).
But still it may be efficient to do a projection first (the first part), otherwise too much data may be fetched from the database.

How to merge two tables into one using mongify

I am planning to migrate my application database from Mysql to Mongo with low schema changes. In my new schema I merged two Mysql tables into one Mongo collection. I want to use mongify (https://github.com/anlek/mongify) gem to populate my existing Mysql data into Mongo with newer schema.
How to do this? Is there a way in mongify to merge two Mysql tables into one?
Mysql tables
user
id
name
nickname
type
user_role
id
role
alias
user_id
I merged the above two tables into single collection in Mongo
user
id
name
type
role
alias
Try Left Join: (Tables will be merged)
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;
Export that data to sql format and upload it to mongodb
SELECT country INTO customerCountry
FROM customers
WHERE customerNumber = p_customerNumber;
CASE customerCountry -- Here you have to see if that alias data is set
WHEN 'USA' THEN
SET p_shiping = '2-day Shipping'; -- here you have to write Update Query
ELSE
SET p_shiping = '5-day Shipping';
END CASE;
I think it might help you
Fetch the data using JOIN from MySQL and load that data into MongoDB:
Try this:
SELECT U.id, U.name, U.type, UR.role
FROM USER U
INNER JOIN user_role UR ON U.id = UR.user_id;
An alternative if its difficult to merge two tables ad-hoc then run a mongo shell script post-hoc; they are very easy to program (couple o' lines of js) and simple to execute. plus one can apply any needed conversion, such as into json/bson arrays permitted in mongo but not the mysql.
assuming a user and user_role collection (or table) in mongo.
db.user_role.find({}).forEach(function(doc) {
var roles = doc.roles;
// convert mysql format here if needed.
//var roles_array = JSON.parse(roles) // or whatever?
//var alias = doc.alias;
// if alias is null empty or ??
// dont upsert to avoid orphaned user_role records
db.user.update({"_id": doc.user_id}, {"roles": roles, "alias", doc.alias }, {upsert: false, multi: false});
}
Then execute using the mongo shell
mongo localhost:27017/test myjsfile.js

Store procedure select all fields from One table using join

I am very frustrated from linq to sql when dealing with many to many relationship with the skip extension. It doesn't allow me to use joinned queries. Not sure it is the case for SQL server 2005 but I am currently using SQL Server 2000.
Now I consider to write a store procedure to fetch a table that is matched by two tables e.g. Album_Photo (Album->Album_Photo<-Photo) and Photo table and only want the Photos data so I match the Album's ID with Album_Photo and use that ID to match the photo. In the store procedure I am just fetch all the joinned data. After that in the linq to sql, I create a new Album object.
e.g.
var albums = (from r in result
where (modifier_id == r.ModifierID || user_id == r.UserID)
select new Album() {
Name = r.Name,
UserID = r.UserID,
ModifierID = r.ModifierID,
ID = r.ID,
DateCreated = r.DateCreated,
Description = r.Description,
Filename = r.Filename
}).AsQueryable();
I used the AsQueryable to get the result as a IQueryable rather than IEnumerable. Later I want to do something with the collection, it gives me this error:
System.InvalidOperationException: The query results cannot be enumerated more than once.
It sounds like you have a situation where the query has already executed by the time you are want to filter it later in your code.
Can you do something like...
var albums = (blah blah blah).AsQueryable().Where(filterClause) when you have enough info to process
what happens if you try albums.where(filter) later on in the code? Is this what you are trying?