Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findOrCreate does not eagerload associations on create #9042

Closed
aprilmintacpineda opened this issue Feb 13, 2018 · 10 comments
Closed

findOrCreate does not eagerload associations on create #9042

aprilmintacpineda opened this issue Feb 13, 2018 · 10 comments

Comments

@aprilmintacpineda
Copy link

aprilmintacpineda commented Feb 13, 2018

What are you doing?

I want findOrCreate to eagerload the associations. Eagerloading associations only works when the record exists, but when it does not exists, it creates the record but it does not eagerload the associations specified.

models.Conversation.findOrCreate({
  where: {
    [ Op.or ]: [
      {
        recipient_user_id: request.signedinUser.id,
        sender_user_id: request.body.user_id
      },
      {
        sender_user_id: request.signedinUser.id,
        recipient_user_id: request.body.user_id
      }
    ]
  },
  include: [
    'recipient',
    'sender',
    models.Chat
  ],
  defaults: {
    /* defaults */
  }
})
.spread(conversation => {
  /* will output undefined */
  console.log(conversation.Chats);
  console.log(conversation.sender);
  console.log(conversation.recipient);
  /* will have no Chats, sender or recipient */
  console.log(conversation);
});

What do you expect to happen?

It should eagerload the associations even when the record was newly created.

What is actually happening?

It does not eagerload the associations when the record was newly created.

Output

Executing (48294410-578a-4ece-bea6-bd4d4d144c17): START TRANSACTION;
Executing (48294410-578a-4ece-bea6-bd4d4d144c17): SELECT `Conversation`.*, `recipient`.`user_id` AS `recipient.user_id`, `recipient`.`first_name` AS `recipient.first_name`, `recipient`.`middle_name` AS `recipient.middle_name`, `recipient`.`surname` AS `recipient.surname`, `recipient`.`email` AS `recipient.email`, `recipient`.`password` AS `recipient.password`, `recipient`.`sex` AS `recipient.sex`, `recipient`.`profile_image` AS `recipient.profile_image`, `recipient`.`confirm_token` AS `recipient.confirm_token`, `recipient`.`is_confirmed` AS `recipient.is_confirmed`, `recipient`.`remember_token` AS `recipient.remember_token`, `recipient`.`created_at` AS `recipient.created_at`, `recipient`.`updated_at` AS `recipient.updated_at`, `sender`.`user_id` AS `sender.user_id`, `sender`.`first_name` AS `sender.first_name`, `sender`.`middle_name` AS `sender.middle_name`, `sender`.`surname` AS `sender.surname`, `sender`.`email` AS `sender.email`, `sender`.`password` AS `sender.password`, `sender`.`sex` AS `sender.sex`, `sender`.`profile_image` AS `sender.profile_image`, `sender`.`confirm_token` AS `sender.confirm_token`, `sender`.`is_confirmed` AS `sender.is_confirmed`, `sender`.`remember_token` AS `sender.remember_token`, `sender`.`created_at` AS `sender.created_at`, `sender`.`updated_at` AS `sender.updated_at`, `Chats`.`chat_id` AS `Chats.chat_id`, `Chats`.`conversation_id` AS `Chats.conversation_id`, `Chats`.`sender_user_id` AS `Chats.sender_user_id`, `Chats`.`message` AS `Chats.message`, `Chats`.`seen` AS `Chats.seen`, `Chats`.`seen_at` AS `Chats.seen_at`, `Chats`.`created_at` AS `Chats.created_at`, `Chats`.`updated_at` AS `Chats.updated_at` FROM (SELECT `Conversation`.`conversation_id`, `Conversation`.`recipient_user_id`, `Conversation`.`sender_user_id`, `Conversation`.`created_at`, `Conversation`.`updated_at` FROM `conversation` AS `Conversation` WHERE ((`Conversation`.`recipient_user_id` = 11737847872 AND `Conversation`.`sender_user_id` = 57611519186) OR (`Conversation`.`sender_user_id` = 11737847872 AND `Conversation`.`recipient_user_id` = 57611519186)) LIMIT 1) AS `Conversation` LEFT OUTER JOIN `user` AS `recipient` ON `Conversation`.`recipient_user_id` = `recipient`.`user_id` LEFT OUTER JOIN `user` AS `sender` ON `Conversation`.`sender_user_id` = `sender`.`user_id` LEFT OUTER JOIN `chat` AS `Chats` ON `Conversation`.`conversation_id` = `Chats`.`conversation_id`;
Executing (48294410-578a-4ece-bea6-bd4d4d144c17): INSERT INTO `conversation` (`conversation_id`,`recipient_user_id`,`sender_user_id`,`created_at`,`updated_at`) VALUES (19390083258,57611519186,11737847872,1518489263032,1518489263032);
Executing (48294410-578a-4ece-bea6-bd4d4d144c17): COMMIT;

I would get an error saying Unhandled rejection TypeError: Cannot read property 'map' of undefined this is related to chats property, it is undefined when the record was newly created by findOrCreate.

here is an example output when the record was newly created.

Conversation {
  dataValues: 
   { conversation_id: 92319661912,
     recipient_user_id: 47872658736,
     sender_user_id: 11737847872,
     created_at: 1518489689514,
     updated_at: 1518489689514 },
  _previousDataValues: 
   { conversation_id: 92319661912,
     recipient_user_id: 47872658736,
     sender_user_id: 11737847872,
     created_at: 1518489689514,
     updated_at: 1518489689514 },
  _changed: 
   { conversation_id: false,
     recipient_user_id: false,
     sender_user_id: false,
     created_at: false,
     updated_at: false },
  _modelOptions: 
   { timestamps: false,
     validate: {},
     freezeTableName: false,
     underscored: true,
     underscoredAll: false,
     paranoid: false,
     rejectOnEmpty: false,
     whereCollection: { [Symbol(or)]: [Array] },
     schema: null,
     schemaDelimiter: '',
     defaultScope: {},
     scopes: [],
     indexes: [],
     name: { plural: 'Conversations', singular: 'Conversation' },
     omitNull: false,
     tableName: 'conversation',
     sequelize: 
      Sequelize {
        options: [Object],
        config: [Object],
        dialect: [Object],
        queryInterface: [Object],
        models: [Object],
        modelManager: [Object],
        connectionManager: [Object],
        importCache: [Object],
        test: [Object] },
     hooks: {},
     uniqueKeys: {} },
  _options: 
   { isNewRecord: true,
     _schema: null,
     _schemaDelimiter: '',
     attributes: undefined,
     include: [ [Object], [Object], [Object] ],
     raw: undefined,
     silent: undefined,
     model: Conversation,
     includeNames: [ 'recipient', 'sender', 'Chats' ],
     includeMap: { recipient: [Object], sender: [Object], Chats: [Object] },
     hasSingleAssociation: true,
     hasMultiAssociation: true,
     topModel: Conversation,
     topLimit: undefined,
     hasDuplicating: true,
     hasRequired: false,
     hasWhere: false,
     hasIncludeWhere: false,
     hasIncludeRequired: false,
     subQuery: false },
  __eagerlyLoadedAssociations: [],
  isNewRecord: false,
  null: undefined }

As you can see, Conversation.sender, Conversation.recipient, and Conversation.Chats are all undefined. Here is an example output when the record exists, therefore, was not newly created.

Conversation {
  dataValues: 
   { conversation_id: 19354653227,
     recipient_user_id: 96979887124,
     sender_user_id: 11737847872,
     created_at: 1518167166608,
     updated_at: 1518167166608,
     recipient: 
      User {
        dataValues: [Object],
        _previousDataValues: [Object],
        _changed: {},
        _modelOptions: [Object],
        _options: [Object],
        __eagerlyLoadedAssociations: [],
        isNewRecord: false },
     sender: 
      User {
        dataValues: [Object],
        _previousDataValues: [Object],
        _changed: {},
        _modelOptions: [Object],
        _options: [Object],
        __eagerlyLoadedAssociations: [],
        isNewRecord: false },
     Chats: [] },
  _previousDataValues: 
   { conversation_id: 19354653227,
     recipient_user_id: 96979887124,
     sender_user_id: 11737847872,
     created_at: 1518167166608,
     updated_at: 1518167166608,
     recipient: 
      User {
        dataValues: [Object],
        _previousDataValues: [Object],
        _changed: {},
        _modelOptions: [Object],
        _options: [Object],
        __eagerlyLoadedAssociations: [],
        isNewRecord: false },
     sender: 
      User {
        dataValues: [Object],
        _previousDataValues: [Object],
        _changed: {},
        _modelOptions: [Object],
        _options: [Object],
        __eagerlyLoadedAssociations: [],
        isNewRecord: false },
     Chats: [] },
  _changed: {},
  _modelOptions: 
   { timestamps: false,
     validate: {},
     freezeTableName: false,
     underscored: true,
     underscoredAll: false,
     paranoid: false,
     rejectOnEmpty: false,
     whereCollection: { [Symbol(or)]: [Array] },
     schema: null,
     schemaDelimiter: '',
     defaultScope: {},
     scopes: [],
     indexes: [],
     name: { plural: 'Conversations', singular: 'Conversation' },
     omitNull: false,
     tableName: 'conversation',
     sequelize: 
      Sequelize {
        options: [Object],
        config: [Object],
        dialect: [Object],
        queryInterface: [Object],
        models: [Object],
        modelManager: [Object],
        connectionManager: [Object],
        importCache: [Object],
        test: [Object] },
     hooks: {},
     uniqueKeys: {} },
  _options: 
   { isNewRecord: false,
     _schema: null,
     _schemaDelimiter: '',
     include: [ [Object], [Object], [Object] ],
     includeNames: [ 'recipient', 'sender', 'Chats' ],
     includeMap: { recipient: [Object], sender: [Object], Chats: [Object] },
     includeValidated: true,
     attributes: 
      [ 'conversation_id',
        'recipient_user_id',
        'sender_user_id',
        'created_at',
        'updated_at' ],
     raw: true },
  __eagerlyLoadedAssociations: [],
  isNewRecord: false,
  recipient: 
   User {
     dataValues: 
      { user_id: 96979887124,
        first_name: 'Noemy',
        middle_name: 'Stroman',
        surname: 'Quigley',
        email: 'Burdette62@yahoo.com',
        password: 'sha1$4a357992$1$2be5ba3699c531a1e4476e310a31f6d5e33d800c',
        sex: 'Male',
        profile_image: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/72/profile-icon.png',
        confirm_token: '6iperKPGqStRjkJOxT',
        is_confirmed: true,
        remember_token: null,
        created_at: 1518164153742,
        updated_at: 1518164153742 },
     _previousDataValues: 
      { user_id: 96979887124,
        first_name: 'Noemy',
        middle_name: 'Stroman',
        surname: 'Quigley',
        email: 'Burdette62@yahoo.com',
        password: 'sha1$4a357992$1$2be5ba3699c531a1e4476e310a31f6d5e33d800c',
        sex: 'Male',
        profile_image: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/72/profile-icon.png',
        confirm_token: '6iperKPGqStRjkJOxT',
        is_confirmed: true,
        remember_token: null,
        created_at: 1518164153742,
        updated_at: 1518164153742 },
     _changed: {},
     _modelOptions: 
      { timestamps: false,
        validate: {},
        freezeTableName: false,
        underscored: true,
        underscoredAll: false,
        paranoid: false,
        rejectOnEmpty: false,
        whereCollection: [Object],
        schema: null,
        schemaDelimiter: '',
        defaultScope: {},
        scopes: [],
        indexes: [],
        name: [Object],
        omitNull: false,
        tableName: 'user',
        sequelize: [Object],
        hooks: {},
        uniqueKeys: {} },
     _options: 
      { isNewRecord: false,
        _schema: null,
        _schemaDelimiter: '',
        include: undefined,
        includeNames: undefined,
        includeMap: undefined,
        includeValidated: true,
        raw: true,
        attributes: undefined },
     __eagerlyLoadedAssociations: [],
     isNewRecord: false },
  sender: 
   User {
     dataValues: 
      { user_id: 11737847872,
        first_name: 'Izabella',
        middle_name: 'Walter',
        surname: 'D\'Amore',
        email: 'Max13@hotmail.com',
        password: 'sha1$e2d19b0d$1$58eb8fd02784ebf610503c9ef1dd9206ef463945',
        sex: 'Male',
        profile_image: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/72/profile-icon.png',
        confirm_token: 'waXx43IdAQRvhlmn0M',
        is_confirmed: true,
        remember_token: 'bl4dwA3sETSj05KCZVFgXQLv8ietuoPfrkH91RNqJOm7hIy2xz',
        created_at: 1518164153737,
        updated_at: 1518164153737 },
     _previousDataValues: 
      { user_id: 11737847872,
        first_name: 'Izabella',
        middle_name: 'Walter',
        surname: 'D\'Amore',
        email: 'Max13@hotmail.com',
        password: 'sha1$e2d19b0d$1$58eb8fd02784ebf610503c9ef1dd9206ef463945',
        sex: 'Male',
        profile_image: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/72/profile-icon.png',
        confirm_token: 'waXx43IdAQRvhlmn0M',
        is_confirmed: true,
        remember_token: 'bl4dwA3sETSj05KCZVFgXQLv8ietuoPfrkH91RNqJOm7hIy2xz',
        created_at: 1518164153737,
        updated_at: 1518164153737 },
     _changed: {},
     _modelOptions: 
      { timestamps: false,
        validate: {},
        freezeTableName: false,
        underscored: true,
        underscoredAll: false,
        paranoid: false,
        rejectOnEmpty: false,
        whereCollection: [Object],
        schema: null,
        schemaDelimiter: '',
        defaultScope: {},
        scopes: [],
        indexes: [],
        name: [Object],
        omitNull: false,
        tableName: 'user',
        sequelize: [Object],
        hooks: {},
        uniqueKeys: {} },
     _options: 
      { isNewRecord: false,
        _schema: null,
        _schemaDelimiter: '',
        include: undefined,
        includeNames: undefined,
        includeMap: undefined,
        includeValidated: true,
        raw: true,
        attributes: undefined },
     __eagerlyLoadedAssociations: [],
     isNewRecord: false },
  Chats: [] }

Dialect: mysql
Dialect version: I don't know what this is asking for..
Database version: mysql Ver 14.14 Distrib 5.7.20, for macos10.12 (x86_64) using EditLine wrapper
Sequelize version: ^4.31.2
Tested with latest release: No (If yes, specify that version)

@sushantdhiman
Copy link
Contributor

sushantdhiman commented Feb 13, 2018

@aprilmintacpineda
Copy link
Author

@sushantdhiman Can you just tell me what's missing? A similar issue was opened a long time ago #1711, and this comment said that it should be supported now, but it doesn't look like so.

@sushantdhiman
Copy link
Contributor

Just check given example and see what you are missing

@aprilmintacpineda
Copy link
Author

Conversation model

import Sequelize from 'sequelize';

export default (sequelize, DataTypes) => {
  let conversation = sequelize.define('Conversation', {
    conversation_id: {
      allowNull: false,
      autoIncrement: false,
      primaryKey: true,
      type: Sequelize.BIGINT(11)
    },
    recipient_user_id: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    },
    sender_user_id: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    },
    created_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11),
    },
    updated_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    }
  }, {
    underscored: true,
    timestamps: false,
    tableName: 'conversation'
  });

  conversation.associate = models => {
    conversation.hasMany(models.Chat, {
      foreignKey: 'conversation_id',
      targetKey: 'conversation_id'
    });

    conversation.belongsTo(models.User, {
      as: 'recipient',
      foreignKey: 'recipient_user_id',
      targetKey: 'user_id'
    });

    conversation.belongsTo(models.User, {
      as: 'sender',
      foreignKey: 'sender_user_id',
      targetKey: 'user_id'
    });
  };

  return conversation;
};

user model

import Sequelize from 'sequelize';

export default (sequelize, DataTypes) => {
  let user = sequelize.define('User', {
    user_id: {
      allowNull: false,
      autoIncrement: false,
      primaryKey: true,
      type: Sequelize.BIGINT(11)
    },
    first_name: {
      type: Sequelize.STRING(70),
      allowNull: false
    },
    middle_name: {
      type: Sequelize.STRING(70),
      allowNull: true
    },
    surname: {
      type: Sequelize.STRING(70),
      allowNull: false
    },
    email: {
      type: Sequelize.STRING(255),
      allowNull: false
    },
    password: {
      type: Sequelize.STRING(255),
      allowNull: false
    },
    sex: {
      type: Sequelize.STRING('6'),
      allowNull: false
    },
    profile_image: {
      type: Sequelize.STRING(255),
      allowNull: true
    },
    confirm_token: {
      type: Sequelize.STRING(72),
      allowNull: false
    },
    is_confirmed: {
      type: Sequelize.BOOLEAN,
      defaultValue: false,
      allowNull: false
    },
    remember_token: {
      type: Sequelize.STRING(50),
      allowNull: true
    },
    created_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11),
    },
    updated_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    }
  }, {
    underscored: true,
    timestamps: false,
    tableName: 'user'
  });

  user.associate = models => {
    user.hasMany(models.Conversation, {
      as: 'received',
      foreignKey: 'recipient_user_id',
      targetKey: 'user_id'
    });

    user.hasMany(models.Conversation, {
      as: 'sent',
      foreignKey: 'sender_user_id',
      targetKey: 'user_id'
    });

    user.hasMany(models.Contact, {
      foreignKey: 'user_id',
      targetKey: 'user_id'
    });

    user.hasMany(models.Service, {
      foreignKey: 'user_id',
      targetKey: 'user_id'
    });
  };

  return user;
};

chat model

import Sequelize from 'sequelize';

export default (sequelize, DataTypes) => {
  let chat = sequelize.define('Chat', {
    chat_id: {
      allowNull: false,
      autoIncrement: false,
      primaryKey: true,
      type: Sequelize.BIGINT(11)
    },
    conversation_id: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    },
    sender_user_id: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    },
    message: {
      allowNull: false,
      type: Sequelize.STRING(5000)
    },
    seen: {
      allowNull: false,
      type: Sequelize.BOOLEAN,
      defaultValue: false
    },
    seen_at: {
      allowNull: true,
      type: Sequelize.DATE
    },
    created_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11),
    },
    updated_at: {
      allowNull: false,
      type: Sequelize.BIGINT(11)
    }
  }, {
    underscored: true,
    timestamps: false,
    tableName: 'chat'
  });

  chat.associate = models => {
    chat.belongsTo(models.Conversation, {
      foreignKey: 'conversation_id',
      target_id: 'conversation_id'
    });

    chat.belongsTo(models.User, {
      foreignKey: 'sender_user_id',
      target_id: 'user_id'
    });
  };

  return chat;
};

@aprilmintacpineda
Copy link
Author

@sushantdhiman are those enough?

@sushantdhiman
Copy link
Contributor

@aprilmintacpineda Point is to produce shortest possible case so I can understand and help you, you are just pasting your project files and asking me is that enough :)

Just open an editor and try to reproduce this issue as SSCCE, away from your project

@aprilmintacpineda
Copy link
Author

aprilmintacpineda commented Feb 13, 2018

@sushantdhiman If I have that much time I would have investigated this issue and probably corrected it myself. I can make a workaround to make it work for my project, but of course, that's not good (from my POV).

@mickhansen I think you can help out with.

@sushantdhiman
Copy link
Contributor

sushantdhiman commented Feb 13, 2018

@aprilmintacpineda So you think we got spare time to solve "your issues" when you don't have enough time to properly present a test case :)

@cyrilchapon
Copy link

@aprilmintacpineda yeah, better silently closing this

@0x1026
Copy link

0x1026 commented Jul 17, 2022

@aprilmintacpineda So you think we got spare time to solve "your issues" when you don't have enough time to properly present a test case :)

It seems that you have had spare time to respond in the only wrong and selfish way, the opposite of trying to help.
This issue would help if there was a solution. But there is only selfishness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants