Задача построения запроса с помощью sequelize - PullRequest
0 голосов
/ 06 марта 2019

У меня проблемы с воссозданием следующего запроса в Sequelize.Я сидел часами, пытаясь понять это.

Я использую camelCase вместо snake_case, поэтому я не могу повторно использовать тот же запрос.

Запрос не будет работать, если я обменяю все переменные snake_cased на camelCase в запросе.Вернусь "отношение \" прямых сообщений \ "не существует".Я не могу получить доступ к таблице directmessages в psql с помощью прямых сообщений TABLE;- но я знаю, что он должен быть там.

Я также не могу понять, как выполнить тот же запрос с помощью sequelize.

В основном мне нужно выбрать каждого пользователя, которого текущий пользователь уже направил.связался с.Либо в качестве отправителя или получателя.

  models.sequelize.query(
    'select distinct on (u.id) u.id, u.username from users as u join direct_messages as dm on (u.id = dm.sender_id) or (u.id = dm.receiver_id) where (:currentUserId = dm.sender_id or :currentUserId = dm.receiver_id) and dm.team_id = :teamId',
    {
      replacements: { currentUserId: user.id, teamId: id },
      model: models.User,
      raw: true,
    },

Вот соответствующие модели для этого запроса:

Модель пользователя:

User.associate = (models) => {
    User.belongsToMany(models.Team, {
        through: models.Member,
        foreignKey: 'userId',
    })
    User.belongsToMany(models.Channel, {
        through: 'channel_member',
        foreignKey: 'userId',
    })

}

Модель DirectMessage:

DirectMessage.associate = (models) => {
    DirectMessage.belongsTo(models.Team, {
        foreignKey: 'teamId',
    })
    DirectMessage.belongsTo(models.User, {
        foreignKey: 'receiverId',
    })
    DirectMessage.belongsTo(models.User, {
        foreignKey: 'senderId',
    })
}

Я пыталсясоздавая запрос с помощью sequelize следующим образом:

models.User.findAll({ 
            include:[{
                model: models.DirectMessage,
                where: {                        
                    teamId, 
                    [models.sequelize.Op.or]: [{senderId: user.id}, {receiverId: user.id}]
                }
            }]
            }, { raw: true })

Я получаю «сообщение»: «directMessage не связано с пользователем!», что, я полагаю, связано с тем, что DirectMessage связан с пользователем, а не с другой стороны.около.

У кого-нибудь есть советы, как мне восстановить этот запрос?

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Здесь есть пара вещей.Во-первых, когда вы используете belongsToMany, вам нужно выполнить ассоциацию в обеих моделях, потому что это отношение M: N, например: у вас также неверный foreignKey в ассоциации.Должно быть что-то вроде этого:

User.associate = (models) => {
  User.belongsToMany(models.Team, {
      through: models.Member,
      foreignKey: 'user_id',
  })

  models.Team.belongsToMany(User, {
      through: models.Member,
      foreignKey: 'team_id',
  })

  // ----------------------------------
  User.belongsToMany(models.Channel, {
      through: 'channel_member',
      foreignKey: 'user_id',
  })

  models.Channel.belongsToMany(user, {
      through: 'channel_member',
      foreignKey: 'channel_id',
  })

}

Теперь, чтобы иметь возможность использовать имена camelCase на javascript и sequelize, а также сохранить snake_case на sql, вы можете сделать это:

module.exports = (sequelize, DataTypes) => {
  const Member = sequelize.define('Member', {
    // here goes your regular fields
    userId: { //now you can use this property on sequelize
      field: 'user_id', //and is linked yo the foreignKey
      type: DataTypes.INTEGER
    },
    teamId: {
      field: 'team_id',
      type: DataTypes.INTEGER
    }
  }
}

И последняя проблема, с которой вы столкнулись при включении, заключается в том, что вы должны указать, какую ассоциацию вы вызываете, и, как вы сказали, вам нужно объявить ассоциацию другим способом, от User до DirectMessage:

User.hasMany(models.DirectMessage, { //there is also hasOne()
  as: 'Sender', // this is important because you have two association from User to  DirectMessage
  foreignKey: 'sender_id',
})

User.hasMany(models.DirectMessage, { //there is also hasOne()
  as: 'Receiver', // this is important because you have two association from User to  DirectMessage
  foreignKey: 'user_id',
})

Теперь вы можете выполнить свой запрос

models.User.findAll({ 
  include:[{
      model: models.DirectMessage,
      as: 'Sender'
      where: {                        
          teamId,
      }
  }]
}, { raw: true })

У меня есть сомнения по этому вопросу, потому что на самом деле вы называете все DirectMessages, то есть senderId и receiverId фильтр не имеет особого смысла.

В любом случае, надеюсь, с этим есть лучшее представление о том, что делать.

0 голосов
/ 07 марта 2019

, что, как я полагаю, связано с тем, что DirectMessage связано с пользователем, а не наоборот.

Я бы тоже так предположил.Достаточно просто связать пользователя с DirectMessage (дважды):

User.hasMany(models.DirectMessage, {foreignKey: 'receiverId', as: 'receivers'});        
User.hasMany(models.DirectMessage, {foreignKey: 'senderId', as: 'senders'});        

Тогда запрос не так уж плох.Обратите внимание, что значение «as» указывает Sequelizer, какой FK использовать, поэтому убедитесь, что hasMany соответствует запросам 'include model

    models.Users.findAll({
        include: [
            {
                model: models.DirectMessage, as: 'receivers',
                attributes:  [[Sequelize.fn('count', 'id'), 'number_received']]
            },
            {
                model: models.DirectMessage, as: 'senders',
                attributes: [[Sequelize.fn('count', 'id'), 'number_sent']]
            }
            ],
        where : {id : user.id}, // parameter
        group : ['id']
    })        

. Затем вам нужно будет проверить, что либо "senders.number_sent", либо "receivers.number_received "не равны нулю и> 0.Теоретически, вы могли бы сделать это с помощью предложения HAVING, но ИМХО это не слишком хорошо реализовано в Sequelize ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...