LoginSignup
0
3

More than 3 years have passed since last update.

BookShelfアノテーションで複数取得する方法で迷ったのでアウトプットする。

Posted at

はじめに

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の構成

  • こんなかんじ Image from Gyazo

階層アノテーション取得方法

  • それぞれのテーブル定義
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書いたので、間違っている事もあると思われますが、ご了承ください。

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3