How to create a relation for User, groups & groups metaData using TypeORM? - mysql

Creating the MySQL Table relationships, and confused to implement which Relationship should be implemented on User -> Groups -> GroupsMetaData.
User.id = OneToMany (Groups)
Groups = ManyToOne (Users)
Groups.id = ManyToMany (GroupsMetaData)
GroupsMetaData = ManyToOne(Groups)
Using TypeORM for implementing this approach.
Users.entity.ts
#OneToMany(type => Groups, groups => groups.uid)
groups:Groups[]
Groups.entity.ts
#ManyToOne(type => User, user => user.groups)
uid:User
Stucked to create the relations for Groups and GroupsMetaData.
Thanks
**It's not a professional way for an explanation, I tried for the best explanation

User entity
#OneToMany(type => Groups, groups => groups.uid)
groups:Groups[]
Group Entity
#ManyToOne(type => User, user => user.groups)
user: User
#ManyToOne(type => GroupMetadata, gmeta => gmeta.groups)
details: GroupMetadata
GroupMetadata Entity
#OneToMany(type => Groups, groups => groups.uid)
groups: Groups[]
With that config you'll have something like this:
A many to many relation between user and groupmetadata using group as junction table. I recommend you to change the name of some tables, group could be called "user_group" and group metadata can be renamed as group.
Let me know if this answers your question

Related

Yii2 GridView display only related records

I have this database structure:
I need the user to get only those reservations in ReservationsSeachModel that are in the warehouse belonging to the user. Model user_has_warehouse has a function getUserHasWarehouse($user_id, $warehouse_id) to check for relations. I am able to get the relations when viewing single, deleting and updating records in controllers. But I cannot make the SearchModel to return reservations that belong to current user.
I cannot depend on Reservation->user_id, because that value is not mandatory and reservations can be inserted publicly with no user_id. How to make the SearchModel work properly so it only shows reservations belonging to the warehouse where user has the warehouse?
ReservationsSearchModel:
$warehouse_id = User_Has_Warehouse::find()->select(['warehouse_id'])->where(['user_id' => Yii::$app->user->id]);
$freezer_type_id = Freezer_type::find()->select(['id'])->where(['warehouse_id' => $warehouse_id]);
$reservation_id = Reservation_freezer_type::find()->select(['reservation_id'])->where(['freezer_type_id'=>$freezer_type_id]);
...
$query->andFilterWhere([
'id' => $reservation_id,
'customer_id' => $this->customer_id,
'user_id' => $this->user_id,
]);
...
But the following did not work for me. What am I doing wrong?
Managed to solve it.
$h = User_Has_Warehouse::find()->select(['warehouse_id'])->where(['user_id' => Yii::$app->user->id]);
$rt = Freezer_type::find()->select(['id'])->where(['warehouse_id' => $h]);
$res = Reservation_freezer_type::find()->select(['reservation_id'])->where(['freezer_type_id' => $rt]);
// grid filtering conditions
$query->andFilterWhere(['id' => $res]);

How to customise a key in json response?

Relationship: Table has many Users.
I'm using "includes" to print the table details with the associated users as:
Table.includes(:users)
But if I use conditions for users, say, users.active as:
Table.includes(:users).where( :users => { active: true } )
I'm getting the tables with users that are active. That works good. But if a table doesn't have active user, it returns empty.
What I need was, to print the table details even if there is no active user (in that case, excluding the user part). i.e., if there is any active user, it has to be printed along the table else only table has to be printed.
So I wrote a filter method in model as:
has_many :active_users, class_name: "User", :conditions => { active: 'yes'}
And, in controller: Table.includes(:active_users).
Now, for json response:
render :json => { :table => #table.as_json(:include => :active_users) }
So the key comes as "active_users".
But I like to have that key as "users" and i'm stuck finding solutions. Can anyone suggest a sol please.
TIA!
Override the Table#as_json to include the users
def as_json(opts={})
super.merge(
users: active_users.as_json(only: [:id, :username, ...]
)
end
I'd recommend whitelisting the user attributes to ensure you don't expose any sensitive information.

Join DB tables with hasMany association - store in array

In a cakePHP application I am building, a profile can have multiple locations; the tables are called "profiles" and "locations" and in the model classes I have defined a HasMany relationship. Now I want the user to be able to search profiles based on their locations. After reading some questions here and the CakePHP Cookbook, I have decided I need to use SQL joins (in reality more tables are involved, and the result of a search should be based on conditions concerning different tables).
I have written the following function inside my Profile model:
public function findProfiles($long, $lat){
$options['joins'] = array(
array('table' => 'locations',
'alias' => 'Location',
'type' => 'Inner',
'conditions' => array('Location.profile_id = Profile.id'))
);
$options['order'] = array('Location.lng ASC'); //this is just as trial
return $this->find('all',$options);
}
The code works, but I get a copy of a profile for each location it possesses. That is, if a profile possesses 5 positions, I get five instances of that profile (each instance containing all five positions!)
How can I achieve this?
[edit]
eg. let's assume I only have one profile, with two positions. I get:
result[0][Profile]
[Position][0]
[1]
[1][Profile]
[Position][0]
[1]
Where the data in result[0] and result[1] is identical.
The problem happens because of the type of join used. With inner join you'll get this return with your query
profile_id location_id
---------------------------
1 2
1 3
And cake understands that as two records of Profile, so you get repeated Profiles with the same info.
If this were all the extent of your problem, I'd say "go with Containable behaviour and forget joins", but since you said there are more tables involved, maybe the type of join can't be changed. So to get the unique Profile without repetitions, you'll have to GROUP BY the query to get
profile_id location_id
---------------------------
1 2 & 3
with a code similar to this
$options['joins'] = array(
array('table' => 'locations',
'alias' => 'Location',
'type' => 'Inner',
'conditions' => array('Location.profile_id = Profile.id')),
'group' => 'Profile.id'
);
and you'll get rid of repetitions. For future problems like this, is best to first check the actual query that gets send to the DB, check yourself if the result that the DB gives you is what you want, and if not, see what you can do in cake to change it.

Cakephp dynamic model/realation tables

I'm trying to implement this structure in my APP (i'll use fantasy model names):
User hasMany Box
Box hasMany Item
Item hasOne Itemdata
"Item" have some metadata/info
"Itemdata" has 2 or 3 mediumblobs
This would be very easy if I want a db with 4 tables: users,boxes,items,itemdata.
In my db structure, due to amount of data, I'd like to split Itemdata in user-dependent tables, like this:
a) user1_itemdatas, user2_itemdatas ...
or at least,
b) myapp_user1.itemdatas, myapp_user2.itemdatas
(where myapp_user* are different DB).
How can I change on the fly the table in model "Itemdatas" when finding/reading data belonging to certain users?
Should I choose for custom query?
Ok I found a way:
I created another database, in app/Config/database.php I added a new connection:
public $itemsdb = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'myuser',
'password' => 'mypass',
'database' => 'myapp_items',
'prefix' => ''
);
Then in Itemdata model I put:
class Itemdata extends AppModel {
public $useDbConfig = 'itemsdb';
..
}
Finally when performing search:
$user_id = $this->getUserByItemId($item_id);
$this->Itemdatas->useTable = 'itemdatas_user_'.$user_id;
$itemdata = $this->Itemdata->find('first',....);
An alternative can be to use user depending table prefix, instead of table name.

Thinking Sphinx - How to give different weights to models when searching multiple models (global search)

Let say I have two indexed models: User and Student.
I want to search on both models but give precedence to User. How can I do that?
Easy:
results = ThinkingSphinx.search(search_term,
:classes => [User, Student],
:index_weights => {'user_core' => 5},
)
student_core will implicitly have a weight of 1.