#はじめに
BookShelfを使ったデータの取り込みで、データベースの依存関係が複数ある場合の
クエリ取得方法で迷ったので、やった内容をアウトプットする。
その為、説明等は適当な部分多い。
作成していたアプリは、ルーム毎にユーザとメッセージを保存する。
メッセージ交換用アプリ
#Bookshelfとは
Node.jsとかで使えるデータベースに対して、データを取得できる便利な道具です。
##アノテーションについて
DBのテーブル同士を関連づけて取得できるものになります。
var Room = Bookshelf.Model.extend({
tableName: 'rooms',
hasTimestamps: true,
messages: function() {
return this.hasMany(Message);
}
});
アノテーションに当たる部分
- hasMany : 一対多(Roomテーブルの1行に紐づくMessageテーブルの行は多数あるって意味)
- belongsTo : 一対一(MessageとUserテーブルで紐づくデータは1行に対して1行のみ)
//Roomテーブルを取得する際に紐ずいているMessageテーブルのデータを取得する。
messages: function() {
return this.hasMany(Message);
}
##DBの構成
##階層アノテーション取得方法
- それぞれのテーブル定義
var Bookshelf = require('bookshelf')(knex);
var User = Bookshelf.Model.extend({
tableName: 'users'
});
var Room = Bookshelf.Model.extend({
tableName: 'rooms',
hasTimestamps: true,
messages: function() {
return this.hasMany(Message);
}
});
var Message = Bookshelf.Model.extend({
tableName: 'messages',
hasTimestamps: true,
user: function() {
return this.belongsTo(User);
}
});
結局のところ、一対多のデータから、さらに一対一のデータを取り出すには、fetchでwithRelatedで
'message.user'のように、Roomテーブルでアソシエーションとして指定したmessageからさらにMessageでアソシエーションした
userを指定するとデータとして取得できる。
/**
* RoomテーブルからroomIdを紐づけてMessageテーブルのデータを取得
* Messageテーブルからい1対1関係のデータを取得する。
**/
new Room().query({where:{id : roomId}})
.fetch({withRelated:['messages','messages.user']})
.then((messageRoom) => {
res.render('chat',{
roomName: messageRoom.attributes.room_name,
roomId : messageRoom.attributes.id,
userName: login.name,
userId: login.id,
message: messageRoom.relations.messages.models
});
var messageTests = messageRoom.relations.messages.models;
for(var val of messageTests){
console.log(val.attributes.message);
}
});
また、一対多の時にデータを取得する場合は、
room.relations.messages.modelsというようにいったんmodelsを指定してから
attributes.[カラム名]といった形でデータを取得する。
一対一の場合には、messages.relations.user.attributes.[カラム名]という形にすればいい。
初めてQiita書いたので、間違っている事もあると思われますが、ご了承ください。