sequlizejs學習筆記整理

1.事務
try {
  const transaction = await sequelize.transaction();
  const user = await User.findOne(..., { transaction });
  await user.update(..., { transaction });
  await transaction.commit();
} catch {
  await transaction.rollback()
}
A syntax for automatically committing or rolling back based on the promise chain resolution is also supported

try {
  await sequelize.transaction(transaction => { // Note that we pass a callback rather than awaiting the call with no arguments
    const user = await User.findOne(..., {transaction});
    await user.update(..., {transaction});
  });
  // Committed
} catch(err) {
  // Rolled back
  console.error(err);
}
2.findOne,Query模式
await ctx.model.query(`select id,mark,UNIX_TIMESTAMP(endTime) as endTime from userPractice where id=${userId}`, { type: 'SELECT' }); // type : select,insert,update,delete
3.findAll,findAndCountAll,findByPk,blukcreate,blukInsert,blukdelete
3.1 findAll
Model.findAll({
  attributes:你可以使用 sequelize.fn 來做聚合:

Model.findAll({
  attributes: [
    'foo',
    [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats'],
    'bar'
  ]
});
SELECT foo, COUNT(hats) AS n_hats, bar FROM ... ['foo', ['bar', 'baz'], 'qux']
});
你可以使用 sequelize.fn 來做聚合:

Model.findAll({
  attributes: [
    'foo',
    [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats'],
    'bar'
  ]
});
SELECT foo, COUNT(hats) AS n_hats, bar FROM ...

3.1findAll({
            where: {
                userId,
                deleted: 'exist'
            },
            order: [['startTime', 'asc']],
            attributes: [['DISTINCT(barId)', 'id']],
        })
       3.2 await this.ctx.model.QnResource.findAll({
            where: { category: 'h5', type, status: 'on', public: 1 },
            order: [
                ['weight', 'DESC'],
                ['createTime', 'DESC']
            ],
            attributes: ['_key']
        })).map(item => item.toJSON());

        await ctx.service.playRankInfo.findAll({
            where: {
                [Op.and]: [
                    where(fn('date', col('createTime')), date),
                ],
                userId,
            },
            attributes: [[literal('max(rating)'), 'score'], 'musicId'],
            group: ['musicId'],
            order: [[literal('max(rating)'), 'asc']],
            offset: 0,
            limit: 3
        });
        const data = await ctx.service.playDurationInfo.findAll({
            where: {
                createTime: {[Op.gt]: dayjs().subtract(6,      'month').format('YYYY-MM-DD')},
                userId
            },
            attributes: [[literal('date(createTime)'), 'day'], [literal('month(createTime)'), 'month'], 'read',
                [literal('sum(duration)'), 'duration']],
            group: [literal('date(createTime)')],
            order: [['createTime', 'desc'] /*, [literal('month(createTime)'), 'desc']*/]
        });

User.findAll({
  where: {
    '$Instruments.size$': { [Op.ne]: 'small' }
  },
  include: [{
    model: Tool,
    as: 'Instruments'
  }]
});
Generated SQL:

生成的 SQL:

SELECT
  `user`.`id`,
  `user`.`name`,
  `Instruments`.`id` AS `Instruments.id`,
  `Instruments`.`name` AS `Instruments.name`,
  `Instruments`.`size` AS `Instruments.size`,
  `Instruments`.`userId` AS `Instruments.userId`
FROM `users` AS `user`
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

區別:
// Inner where, with default `required: true`
await User.findAll({
  include: {
    model: Tool,
    as: 'Instruments',
    where: {
      size: { [Op.ne]: 'small' }
    }
  }
});

// Inner where, `required: false`
await User.findAll({
  include: {
    model: Tool,
    as: 'Instruments',
    where: {
      size: { [Op.ne]: 'small' }
    },
    required: false //==左連接==
  }
});

// Top-level where, with default `required: false`
await User.findAll({
  where: {
    '$Instruments.size$': { [Op.ne]: 'small' }
  },
  include: {
    model: Tool,
    as: 'Instruments'
  }
});

// Top-level where, `required: true`
await User.findAll({
  where: {
    '$Instruments.size$': { [Op.ne]: 'small' }
  },
  include: {
    model: Tool,
    as: 'Instruments',
    required: true
  }
});
Generated SQLs, in order:

按順序生成的 SQLs:

-- Inner where, with default `required: true`
SELECT [...] FROM `users` AS `user`
INNER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
  AND `Instruments`.`size` != 'small';

-- Inner where, `required: false`
SELECT [...] FROM `users` AS `user
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
  AND `Instruments`.`size` != 'small';

-- Top-level where, with default `required: false`
SELECT [...] FROM `users` AS `user`
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

-- Top-level where, `required: true`
SELECT [...] FROM `users` AS `user`
INNER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

User.findAll({
  include: [
    {
      model: Grant,
      include: [User, Profile]
    },
    {
      model: Profile,
      include: {
        model: User,
        include: {
          model: Grant,
          include: [User, Profile]
        }
      }
    }
  ]
});

await Foo.findAll({
  include: {
    model: Bar,
    limit: 2,
    include: [{
      model: Baz,
      limit: 2,
      attributes: {
        exclude: ['name']  //除了Name屬性不顯示
      },
      include: Qux
    }]
  }
});

3.3  Post.findAll({
    attributes: {
        include: [
            [
                sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM reactions AS reaction
                    WHERE
                        reaction.postId = post.id
                        AND
                        reaction.type = "Laugh"
                )`),
                'laughReactionsCount'
            ]
        ]
    },
    order: [
        [sequelize.literal('laughReactionsCount'), 'DESC']
    ]
});
以上提供了以下輸出:

[
  {
    "id": 1,
    "content": "Hello World",
    "laughReactionsCount": 1
  },
  {
    "id": 2,
    "content": "My Second Post",
    "laughReactionsCount": 3
  }
]
3.2 findAndCountAll
const { count, rows } = await Project.findAndCountAll({
  where: {
    title: {
      [Op.like]: 'foo%'
    }
  },
  offset: 10,
  limit: 2
});
console.log(count);
console.log(rows);

const result = await Model.findAndCountAll({
  where: ...,
  limit: 12,
  offset: 12
});

# In the above example, `result.rows` will contain rows 13 through 24, while `result.count` will return the total number of rows that matched your query.

# When you add includes, only those which are required (either because they have a where clause, or because `required` is explicitly set to true on the include) will be added to the count part.

# Suppose you want to find all users who have a profile attached:

User.findAndCountAll({
  include: [
     { model: Profile, required: true}
  ],
  limit: 3
});

# Because the include for `Profile` has `required` set it will result in an inner join, and only the users who have a profile will be counted. If we remove `required` from the include, both users with and without profiles will be counted
3.3 .bulkInsert,bulkDelete
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('Users', [{
      firstName: 'John',
      lastName: 'Doe',
      email: '[email protected]',
      createdAt: new Date(),
      updatedAt: new Date()
    }]);
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('Users', null, {});
  }
};
3.4 findByPk
const ourUser = await User.findByPk(1, {
    include: [User.associations.projects],
    rejectOnEmpty: true, // Specifying true here removes `null` from the return type!
  });

  // Note the `!` null assertion since TS can't know if we included
  // the model or not
  console.log(ourUser.projects![0].name);
  async function doStuff() {
  const instance = await UserModel.findByPk(1, {
    rejectOnEmpty: true,
  });
  console.log(instance.id);
}
const project = await Project.findByPk(123);
if (project === null) {
  console.log('Not found!');
} else {
  console.log(project instanceof Project); // true
  // Its primary key is 123
}
3.5 findOne
const project = await Project.findOne({ where: { title: 'My Title' } });
if (project === null) {
  console.log('Not found!');
} else {
  console.log(project instanceof Project); // true
  console.log(project.title); // 'My Title'
}
3.6 destory
// Delete everyone named "Jane"
await User.destroy({
  where: {
    firstName: "Jane"
  }
});
To destroy everything the TRUNCATE SQL can be used:

爲了摧毀 TRUNCATE SQL 所能使用的一切:

// Truncate the table
await User.destroy({
  truncate: true
});
3.7 blukCreate
const captains = await Captain.bulkCreate([
  { name: 'Jack Sparrow' },
  { name: 'Davy Jones' }
]);
console.log(captains.length); // 2
console.log(captains[0] instanceof Captain); // true
console.log(captains[0].name); // 'Jack Sparrow'
console.log(captains[0].id);
4.一對一,多對一關係model定義
https://sequelize.org/master/manual/assocs.html#implementation

4.1 Defining the Sequelize associations
The four association types are defined in a very similar way. Let's say we have two models, A and B. Telling Sequelize that you want an association between the two needs just a function call:

const A = sequelize.define('A', /* ... */);
const B = sequelize.define('B', /* ... */);

A.hasOne(B); // A HasOne B
A.belongsTo(B); // A BelongsTo B
A.hasMany(B); // A HasMany B
A.belongsToMany(B, { through: 'C' }); // A BelongsToMany B through the junction table C
They all accept an options object as a second parameter (optional for the first three, mandatory for belongsToMany containing at least the through property):

A.hasOne(B, { /* options */ });
A.belongsTo(B, { /* options */ });
A.hasMany(B, { /* options */ });
A.belongsToMany(B, { through: 'C', /* options */ });

4.2
const Movie = sequelize.define('Movie', { name: DataTypes.STRING });
const Actor = sequelize.define('Actor', { name: DataTypes.STRING });
const ActorMovies = sequelize.define('ActorMovies', {
  MovieId: {
    type: DataTypes.INTEGER,
    references: {
      model: Movie, // 'Movies' would also work
      key: 'id'
    }
  },
  ActorId: {
    type: DataTypes.INTEGER,
    references: {
      model: Actor, // 'Actors' would also work
      key: 'id'
    }
  }
});
Movie.belongsToMany(Actor, { through: ActorMovies });
Actor.belongsToMany(Movie, { through: ActorMovies });
Belongs-To-Many 在 through model 上創建了一個獨特的鍵。可以使用 uniqueKey 選項重寫此唯一鍵名。若要防止創建此唯一鍵,請使用 unique: false 選項。

Project.belongsToMany(User, { through: UserProjects, uniqueKey: 'my_custom_unique' })

Goods.hasMany(GoodsCompose, {
        foreignKey: 'goodsId', sourceKey: 'id', as: 'goodsComposes'
    })
GoodsCompose.belongsTo(Goods, {
        foreignKey: 'goodsId', targetKey: 'id', as: 'goods'
 })
 A.belongsToMany (b)涉及一個額外的表(連接表) ,因此 sourceKey 和 targetKey 都是可用的,sourceKey 對應於 a (源)中的某個字段,targetKey 對應於 b (目標)中的某個字段。

//多對多
爲了提供最大的靈活性,讓我們在這裏再次使用超多對多關係結構:

// Super Many-to-Many relationship between Player and GameTeam
const PlayerGameTeam = sequelize.define('PlayerGameTeam', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    allowNull: false
  }
});
Player.belongsToMany(GameTeam, { through: PlayerGameTeam });
GameTeam.belongsToMany(Player, { through: PlayerGameTeam });
PlayerGameTeam.belongsTo(Player);
PlayerGameTeam.belongsTo(GameTeam);
Player.hasMany(PlayerGameTeam);
GameTeam.hasMany(PlayerGameTeam);




//完整例子
const { Sequelize, Op, Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:', {
  define: { timestamps: false } // Just for less clutter in this example
});
const Player = sequelize.define('Player', { username: DataTypes.STRING });
const Team = sequelize.define('Team', { name: DataTypes.STRING });
const Game = sequelize.define('Game', { name: DataTypes.INTEGER });

// We apply a Super Many-to-Many relationship between Game and Team
const GameTeam = sequelize.define('GameTeam', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    allowNull: false
  }
});
Team.belongsToMany(Game, { through: GameTeam });
Game.belongsToMany(Team, { through: GameTeam });
GameTeam.belongsTo(Game);
GameTeam.belongsTo(Team);
Game.hasMany(GameTeam);
Team.hasMany(GameTeam);

// We apply a Super Many-to-Many relationship between Player and GameTeam
const PlayerGameTeam = sequelize.define('PlayerGameTeam', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    allowNull: false
  }
});
Player.belongsToMany(GameTeam, { through: PlayerGameTeam });
GameTeam.belongsToMany(Player, { through: PlayerGameTeam });
PlayerGameTeam.belongsTo(Player);
PlayerGameTeam.belongsTo(GameTeam);
Player.hasMany(PlayerGameTeam);
GameTeam.hasMany(PlayerGameTeam);

(async () => {

  await sequelize.sync();
  await Player.bulkCreate([
    { username: 's0me0ne' },
    { username: 'empty' },
    { username: 'greenhead' },
    { username: 'not_spock' },
    { username: 'bowl_of_petunias' }
  ]);
  await Game.bulkCreate([
    { name: 'The Big Clash' },
    { name: 'Winter Showdown' },
    { name: 'Summer Beatdown' }
  ]);
  await Team.bulkCreate([
    { name: 'The Martians' },
    { name: 'The Earthlings' },
    { name: 'The Plutonians' }
  ]);

  // Let's start defining which teams were in which games. This can be done
  // in several ways, such as calling `.setTeams` on each game. However, for
  // brevity, we will use direct `create` calls instead, referring directly
  // to the IDs we want. We know that IDs are given in order starting from 1.
  await GameTeam.bulkCreate([
    { GameId: 1, TeamId: 1 },   // this GameTeam will get id 1
    { GameId: 1, TeamId: 2 },   // this GameTeam will get id 2
    { GameId: 2, TeamId: 1 },   // this GameTeam will get id 3
    { GameId: 2, TeamId: 3 },   // this GameTeam will get id 4
    { GameId: 3, TeamId: 2 },   // this GameTeam will get id 5
    { GameId: 3, TeamId: 3 }    // this GameTeam will get id 6
  ]);

  // Now let's specify players.
  // For brevity, let's do it only for the second game (Winter Showdown).
  // Let's say that that s0me0ne and greenhead played for The Martians, while
  // not_spock and bowl_of_petunias played for The Plutonians:
  await PlayerGameTeam.bulkCreate([
    // In 'Winter Showdown' (i.e. GameTeamIds 3 and 4):
    { PlayerId: 1, GameTeamId: 3 },   // s0me0ne played for The Martians
    { PlayerId: 3, GameTeamId: 3 },   // greenhead played for The Martians
    { PlayerId: 4, GameTeamId: 4 },   // not_spock played for The Plutonians
    { PlayerId: 5, GameTeamId: 4 }    // bowl_of_petunias played for The Plutonians
  ]);

  // Now we can make queries!
  const game = await Game.findOne({
    where: {
      name: "Winter Showdown"
    },
    include: {
      model: GameTeam,
      include: [
        {
          model: Player,
          through: { attributes: [] } // Hide unwanted `PlayerGameTeam` nested object from results
        },
        Team
      ]
    }
  });

  console.log(`Found game: "${game.name}"`);
  for (let i = 0; i < game.GameTeams.length; i++) {
    const team = game.GameTeams[i].Team;
    const players = game.GameTeams[i].Players;
    console.log(`- Team "${team.name}" played game "${game.name}" with the following players:`);
    console.log(players.map(p => `--- ${p.username}`).join('\n'));
  }

})();
5.延時加載,即時加載
const Ship = sequelize.define('ship', {
  name: DataTypes.TEXT,
  crewCapacity: DataTypes.INTEGER,
  amountOfSails: DataTypes.INTEGER
}, { timestamps: false });
const Captain = sequelize.define('captain', {
  name: DataTypes.TEXT,
  skillLevel: {
    type: DataTypes.INTEGER,
    validate: { min: 1, max: 10 }
  },
  type: {
            type: DataTypes.STRING(20),
            allowNull: true,
            comment: '',
        },
   plat: {
            type: DataTypes.STRING(20),
            allowNull: true,
            comment: '',
        },
    state: {
            type: DataTypes.ENUM,
            values: ['dimission', 'active'],
            allowNull: false,
            defaultValue: 'active',
            comment: '人員戶目前狀態(離職,在職)',
        }
}, { timestamps: false });
Captain.hasOne(Ship);
Ship.belongsTo(Captain);

5.1延時加載
const awesomeCaptain = await Captain.findOne({
  where: {
    name: "Jack Sparrow"
  }
});
// Do stuff with the fetched captain
console.log('Name:', awesomeCaptain.name);
console.log('Skill Level:', awesomeCaptain.skillLevel);
// Now we want information about his ship!
const hisShip = await awesomeCaptain.getShip();
// Do stuff with the ship
console.log('Ship Name:', hisShip.name);
console.log('Amount of Sails:', hisShip.amountOfSails);

5.2即時加載
const awesomeCaptain = await Captain.findOne({
  where: {
    name: "Jack Sparrow"
  },
  include: Ship
});
// Now the ship comes with it
console.log('Name:', awesomeCaptain.name);
console.log('Skill Level:', awesomeCaptain.skillLevel);
console.log('Ship Name:', awesomeCaptain.ship.name);
console.log('Amount of Sails:', awesomeCaptain.ship.amountOfSails);

await this.model.findAll({
        attributes: ['id', 'name', 'compose', 'discount'],
        where: {
          compose: 'topup',
        },
        include: [{
            model: GoodsCompose,
            as: 'goodsComposes',
        }]})
await this.service.mktExam.findOne({
            where: { id },
            include: [{
                model: MktExamQuestionLib, as: 'mktExamQuestionLibs',
                include: [{
                    model: MktQuestionLib, as: 'mktQuestionLib',
                    include: [{ model: MktQuestionOpt, as: 'mktQuestionOpts' }],
                }]
            }]
        })
6.sequelize數據庫查詢的Op方法條件查詢
const { Op } = require("sequelize");
Post.findAll({
  where: {
    [Op.and]: [
      { authorId: 12 },
      { status: 'active' }
    ]
  }
});
// SELECT * FROM post WHERE authorId = 12 AND status = 'active';
An OR can be easily performed in a similar way:

一個或者可以很容易地以類似的方式執行:

const { Op } = require("sequelize");
Post.findAll({
  where: {
    [Op.or]: [
      { authorId: 12 },
      { authorId: 13 }
    ]
  }
});
// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;
Since the above was an OR involving the same field, Sequelize allows you to use a slightly different structure which is more readable and generates the same behavior:

因爲上面的是一個涉及相同字段的 OR,Sequelize 允許你使用稍微不同的結構,這個結構更具可讀性,併產生相同的行爲:

const { Op } = require("sequelize");
Post.destroy({
  where: {
    authorId: {
      [Op.or]: [12, 13]
    }
  }
});
// DELETE FROM post WHERE authorId = 12 OR authorId = 13;

const op = models.Sequelize.Op;
  let {age} = req.query;
  let user = await models.User.findAll({
    where: { 
      age: {
        [op.between]: [0, 24] // 查詢年齡在0-24歲的
      }
    }
  })
[Op.like]: 'Foo %'
adjacent: 鄰近的 [Op.adjacent]: [1, 2]

all:所有 [Op.gt]: { [Op.all]: literal('SELECT 1') }

and:並且 [Op.and]: {a: 5}

any:任意 [Op.any]: [2,3]

between:之間 [Op.between]: [10, 20]

col:

contained:

contains:

endsWith:以結束 [Op.endsWith]: 'm'

eq:= 等於 [Op.eq]: 12

gt:> 大於 [Op.gt]: 6

gte:>= 大於等於 [Op.gte]: 6

iLike:

in:查詢包含的狀態 [Op.in]: [12, 25]

iRegexp:

is:是否,判斷類 [Op.is]: null

like:模糊匹配,包含 [Op.like]: '%m%'

lt:< 小於 [Op.lt]: 23

lte:<= 小於等於 [Op.lte]: 10

ne:!= 不等於 [Op.ne]: 23

noExtendLeft:

noExtendRight:

not:非查詢 [Op.not]: null

notBetween:不在xx和xx之間的 [Op.notBetween]: [11, 23]

notILike:

notIn:查詢不包含的狀態 [Op.notIn]: [12, 25]

notIRegexp:

notLike:模糊匹配,不包含 [Op.notLike]: '%m%'

notRegexp:正則,不以開始 [Op.notRegexp]: '^[h|a|t]'

or:或者 where:{ [Op.or]:[ {parent_id:id}, {id:id} ] }

overlap:重疊部分 [Op.overlap]: [1, 2]

placeholder:佔位符

regexp:正則,以開始 [Op.regexp]: '^[h|a|t]'

startsWith:字符串,以*開始 [Op.startsWith]: 'j'

strictLeft:

strictRight:

substring:模糊匹配 [Op.substring]: 'oh'

values:
const {or, and, gt, lt} = Sequelize.Op;

Model.findAll({
  where: {
    name: 'a project',
    [or]: [
      {id: [1, 2, 3]},
      {
        [and]: [
          {id: {[gt]: 10}},
          {id: {[lt]: 100}}
        ]
      }
    ]
  }
});

# WHERE `Model`.`name` = 'a project' AND (`Model`.`id` IN (1, 2, 3) OR (`Model`.`id` > 10 AND `Model`.`id` < 100));
onst {gt, lte, ne, in: opIn} = Sequelize.Op;

Model.findAll({
  where: {
    attr1: {
      [gt]: 50
    },
    attr2: {
      [lte]: 45
    },
    attr3: {
      [opIn]: [1,2,3]
    },
    attr4: {
      [ne]: 5
    }
  }
})
7.刪除
class Post extends Model {}
Post.init({ /* attributes here */ }, {
  sequelize,
  paranoid: true,

  // If you want to give a custom name to the deletedAt column
  deletedAt: 'destroyTime'
});

當你調用 destroy 方法時,會發生一個軟刪除:

await Post.destroy({
  where: {
    id: 1
  }
});
// UPDATE "posts" SET "deletedAt"=[timestamp] WHERE "deletedAt" IS NULL AND "id" = 1


如果你真的想要一個硬刪除,而你的模型是偏執型的,你可以使用 force: true 選項:

await Post.destroy({
  where: {
    id: 1
  },
  force: true
});
// DELETE FROM "posts" WHERE "id" = 1
如果確實想讓查詢查看軟刪除記錄,可以將 paranoid: false 選項傳遞給查詢方法。例如:

await Post.findByPk(123); // This will return `null` if the record of id 123 is soft-deleted
await Post.findByPk(123, { paranoid: false }); // This will retrieve the record

await Post.findAll({
  where: { foo: 'bar' }
}); // This will not retrieve soft-deleted records

await Post.findAll({
  where: { foo: 'bar' },
  paranoid: false
})
8.左右連接
注意: 只有在需要是假的時候才尊重右。

User.findAll({
  include: [{
    model: Task // will create a left join
  }]
});
User.findAll({
  include: [{
    model: Task,
    right: true // will create a right join
  }]
});
User.findAll({
  include: [{
    model: Task,
    required: true,
    right: true // has no effect, will create an inner join
  }]
});
User.findAll({
  include: [{
    model: Task,
    where: { name: { [Op.ne]: 'empty trash' } },
    right: true // has no effect, will create an inner join
  }]
});
User.findAll({
  include: [{
    model: Tool,
    where: { name: { [Op.ne]: 'empty trash' } },
    required: false // will create a left join
  }]
});
User.findAll({
  include: [{
    model: Tool,
    where: { name: { [Op.ne]: 'empty trash' } },
    required: false
    right: true // will create a right join
  }]
});

要包含所有關聯的模型,可以使用 all 和 nested 選項:

// Fetch all models associated with User
User.findAll({ include: { all: true }});

// Fetch all models associated with User and their nested associations (recursively)
User.findAll({ include: { all: true, nested: true }});
9.create的時候建立連接
https://sequelize.org/master/manual/creating-with-associations.html

class Product extends Model {}
Product.init({
  title: Sequelize.STRING
}, { sequelize, modelName: 'product' });
class User extends Model {}
User.init({
  firstName: Sequelize.STRING,
  lastName: Sequelize.STRING
}, { sequelize, modelName: 'user' });
class Address extends Model {}
Address.init({
  type: DataTypes.STRING,
  line1: Sequelize.STRING,
  line2: Sequelize.STRING,
  city: Sequelize.STRING,
  state: Sequelize.STRING,
  zip: Sequelize.STRING,
}, { sequelize, modelName: 'address' });

// We save the return values of the association setup calls to use them later
Product.User = Product.belongsTo(User);
User.Addresses = User.hasMany(Address);

return Product.create({
  title: 'Chair',
  user: {
    firstName: 'Mick',
    lastName: 'Broadstone',
    addresses: [{
      type: 'home',
      line1: '100 Main St.',
      city: 'Austin',
      state: 'TX',
      zip: '78704'
    }]
  }
}, {
  include: [{
    association: Product.User,
    include: [ User.Addresses ]
  }]
});

//別名:
const Creator = Product.belongsTo(User, { as: 'creator' });

return Product.create({
  title: 'Chair',
  creator: {
    firstName: 'Matt',
    lastName: 'Hansen'
  }
}, {
  include: [ Creator ]
});
10.子查詢只選擇需要的字段顯示
10.1 但是,如果只需要 through 表的某些屬性,可以在 attributes 選項中提供具有所需屬性的數組。例如,如果您只想要 through 表中的 selfGranted 屬性:

User.findOne({
  include: {
    model: Profile,
    through: {
      attributes: ['selfGranted']
    }
  }
});
結果:{
  "id": 4,
  "username": "p4dm3",
  "points": 1000,
  "profiles": [
    {
      "id": 6,
      "name": "queen",
      "grant": {
        "selfGranted": false
      }
    }
  ]
}


10.2 如果您根本不需要嵌套的授權字段,請使用屬性: [] :

User.findOne({
  include: {
    model: Profile,
    through: {
      attributes: []
    }
  }
});
Output:

輸出:

{
  "id": 4,
  "username": "p4dm3",
  "points": 1000,
  "profiles": [
    {
      "id": 6,
      "name": "queen"
    }
  ]
}
11.事務隔離級別
啓動事務時可能使用的隔離級別:

const { Transaction } = require('sequelize');

// The following are valid isolation levels:
Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED // "READ UNCOMMITTED"
Transaction.ISOLATION_LEVELS.READ_COMMITTED // "READ COMMITTED"
Transaction.ISOLATION_LEVELS.REPEATABLE_READ  // "REPEATABLE READ"
Transaction.ISOLATION_LEVELS.SERIALIZABLE // "SERIALIZABLE"
By default, sequelize uses the isolation level of the database. If you want to use a different isolation level, pass in the desired level as the first argument:

默認情況下,sequelize 使用數據庫的隔離級別。如果您想使用不同的隔離級別,請將所需的級別作爲第一個參數傳入:

const { Transaction } = require('sequelize');

await sequelize.transaction({
  isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
}, async (t) => {
  // Your code
});


你也可以全局覆蓋 isolationLevel 設置,在 Sequelize 構造函數中有一個選項:

const { Sequelize, Transaction } = require('sequelize');

const sequelize = new Sequelize('sqlite::memory:', {
  isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
});
12.model定義的類型
import { DataTypes } from 'sequelize';

12.1枚舉
sequelize.define('foo', {
  states: {
    type: DataTypes.ENUM,
    values: ['active', 'pending', 'deleted'],
    defaultValue: 'pending'
  }
});
12.2 String
apk: {
            type: DataTypes.STRING(32),//不寫括號,默認255長度
            allowNull: false,
            comment: '',
        }
12.3 Integer
 romIndex: {
            type: DataTypes.INTEGER,
            allowNull: false,
            comment: '',
        }
12.4 table和model名字不一樣時
class User extends Model {}
User.init({
  // ...
}, {
  modelName: 'user',
  tableName: 'users',
  sequelize,
});
12.4 列名和model屬性名不一樣時
class MyModel extends Model {}
MyModel.init({
  userId: {
    type: DataTypes.INTEGER,
    field: 'user_id'
  }
}, { sequelize });
12.5 在model中定義主鍵
class Collection extends Model {}
Collection.init({
  uid: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true // Automatically gets converted to SERIAL for postgres
  }
}, { sequelize });

class Collection extends Model {}
Collection.init({
  uuid: {
    type: DataTypes.UUID,
    primaryKey: true
  }
}, { sequelize class Collection extends Model {}
Collection.init({
  uid: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true // Automatically gets converted to SERIAL for postgres
  }
}, { sequelize });

class Collection extends Model {}
Collection.init({
  uuid: {
    type: DataTypes.UUID,
    primaryKey: true
  }
}, { sequelize });

id: {
      type: DataTypes.INTEGER.UNSIGNED,
      autoIncrement: true,
      primaryKey: true,
    }
    )
12.6 在model中定義外鍵
Organization.belongsTo(User, { foreignKey: 'owner_id' });
User.hasOne(Organization, { foreignKey: 'owner_id' });

// 1:M
Project.hasMany(Task, { foreignKey: 'tasks_pk' });
Task.belongsTo(Project, { foreignKey: 'tasks_pk' });

// N:M
User.belongsToMany(Role, { through: 'user_has_roles', foreignKey: 'user_role_user_id' });
Role.belongsToMany(User, { through: 'user_has_roles', foreignKey: 'roles_identifier' });
12.7 Boolean
Project.init({
  columnA: {
    type: Sequelize.BOOLEAN,
    validate: {
      is: ['[a-z]','i'],        // will only allow letters
      max: 23,                  // only allow values <= 23
      isIn: {
        args: [['en', 'zh']],
        msg: "Must be English or Chinese"
      }
    },
    field: 'column_a'
    // Other attributes here
  },
  columnB: Sequelize.STRING,
  columnC: 'MY VERY OWN COLUMN TYPE'
}, {sequelize})
13.在沒有約束的情況下強制執行外鍵引用
有時您可能希望引用另一個表,而不需要添加任何約束或關聯。在這種情況下,您可以手動將引用屬性添加到模式定義中,並標記它們之間的關係.
class Trainer extends Model {}
Trainer.init({
  firstName: Sequelize.STRING,
  lastName: Sequelize.STRING
}, { sequelize, modelName: 'trainer' });

// Series will have a trainerId = Trainer.id foreign reference key
// after we call Trainer.hasMany(series)
class Series extends Model {}
Series.init({
  title: Sequelize.STRING,
  subTitle: Sequelize.STRING,
  description: Sequelize.TEXT,
  // Set FK relationship (hasMany) with `Trainer`
  trainerId: {
    type: DataTypes.INTEGER,
    references: {
      model: Trainer,
      key: 'id'
    }
  }
}, { sequelize, modelName: 'series' });
/ Video will have seriesId = Series.id foreign reference key
// after we call Series.hasOne(Video)
class Video extends Model {}
Video.init({
  title: Sequelize.STRING,
  sequence: Sequelize.INTEGER,
  description: Sequelize.TEXT,
  // set relationship (hasOne) with `Series`
  seriesId: {
    type: DataTypes.INTEGER,
    references: {
      model: Series, // Can be both a string representing the table name or a Sequelize model
      key: 'id'
    }
  }
}, { sequelize, modelName: 'video' });

Series.hasOne(Video);
Trainer.hasMany(Series);
14.模型添加索引
Sequelize supports adding indexes to the model definition which will be created on sequelize.sync().

const User = sequelize.define('User', { /* attributes */ }, {
  indexes: [
    // Create a unique index on email
    {
      unique: true,
      fields: ['email']
    },

    // Creates a gin index on data with the jsonb_path_ops operator
    {
      fields: ['data'],
      using: 'gin',
      operator: 'jsonb_path_ops'
    },

    // By default index name will be [table]_[fields]
    // Creates a multi column partial index
    {
      name: 'public_by_author',
      fields: ['author', 'status'],
      where: {
        status: 'public'
      }
    },

    // A BTREE index with an ordered field
    {
      name: 'title_index',
      using: 'BTREE',
      fields: [
        'author',
        {
          attribute: 'title',
          collate: 'en_US',
          order: 'DESC',
          length: 5
        }
      ]
    }
  ]
});
15.副本集
https://sequelize.org/master/manual/read-replication.html

const sequelize = new Sequelize('database', null, null, {
  dialect: 'mysql',
  port: 3306
  replication: {
    read: [
      { host: '8.8.8.8', username: 'read-1-username', password: process.env.READ_DB_1_PW },
      { host: '9.9.9.9', username: 'read-2-username', password: process.env.READ_DB_2_PW }
    ],
    write: { host: '1.1.1.1', username: 'write-username', password: process.env.WRITE_DB_PW }
  },
  pool: { // If you want to override the options used for the read/write pool you can do so here
    max: 20,
    idle: 30000
  },
})
16.其他輔助包
https://sequelize.org/master/manual/resources.html

17.原始查詢
https://blog.csdn.net/awhlmcyn/article/details/79816494

const [results, metadata] = await sequelize.query("UPDATE users SET y = 42 WHERE x = 12");
// Results will be an empty array and metadata will contain the number of affected rows.

const { QueryTypes } = require('sequelize');
const users = await sequelize.query("SELECT * FROM `users`", { type: QueryTypes.SELECT });
// We didn't need to destructure the result here - the results were returned directly
18.排序
Subtask.findAll({
  order: [
    // Will escape title and validate DESC against a list of valid direction parameters
    ['title', 'DESC'],

    // Will order by max(age)
    sequelize.fn('max', sequelize.col('age')),

    // Will order by max(age) DESC
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],

    // Will order by  otherfunction(`col1`, 12, 'lalala') DESC
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],

    // Will order an associated model's createdAt using the model name as the association's name.
    [Task, 'createdAt', 'DESC'],

    // Will order through an associated model's createdAt using the model names as the associations' names.
    [Task, Project, 'createdAt', 'DESC'],

    // Will order by an associated model's createdAt using the name of the association.
    ['Task', 'createdAt', 'DESC'],

    // Will order by a nested associated model's createdAt using the names of the associations.
    ['Task', 'Project', 'createdAt', 'DESC'],

    // Will order by an associated model's createdAt using an association object. (preferred method)
    [Subtask.associations.Task, 'createdAt', 'DESC'],

    // Will order by a nested associated model's createdAt using association objects. (preferred method)
    [Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],

    // Will order by an associated model's createdAt using a simple association object.
    [{model: Task, as: 'Task'}, 'createdAt', 'DESC'],

    // Will order by a nested associated model's createdAt simple association objects.
    [{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
  ],

  // Will order by max age descending
  order: sequelize.literal('max(age) DESC'),

  // Will order by max age ascending assuming ascending is the default order when direction is omitted
  order: sequelize.fn('max', sequelize.col('age')),

  // Will order by age ascending assuming ascending is the default order when direction is omitted
  order: sequelize.col('age'),

  // Will order randomly based on the dialect (instead of fn('RAND') or fn('RANDOM'))
  order: sequelize.random()
});

Foo.findOne({
  order: [
    // will return `name`
    ['name'],
    // will return `username` DESC
    ['username', 'DESC'],
    // will return max(`age`)
    sequelize.fn('max', sequelize.col('age')),
    // will return max(`age`) DESC
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    // will return otherfunction(`col1`, 12, 'lalala') DESC
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    // will return otherfunction(awesomefunction(`col`)) DESC, This nesting is potentially infinite!
    [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
  ]
});
19.查詢條件操作符
const Op = Sequelize.Op;
const operatorsAliases = {
  $eq: Op.eq,
  $ne: Op.ne,
  $gte: Op.gte,
  $gt: Op.gt,
  $lte: Op.lte,
  $lt: Op.lt,
  $not: Op.not,
  $in: Op.in,
  $notIn: Op.notIn,
  $is: Op.is,
  $like: Op.like,
  $notLike: Op.notLike,
  $iLike: Op.iLike,
  $notILike: Op.notILike,
  $regexp: Op.regexp,
  $notRegexp: Op.notRegexp,
  $iRegexp: Op.iRegexp,
  $notIRegexp: Op.notIRegexp,
  $between: Op.between,
  $notBetween: Op.notBetween,
  $overlap: Op.overlap,
  $contains: Op.contains,
  $contained: Op.contained,
  $adjacent: Op.adjacent,
  $strictLeft: Op.strictLeft,
  $strictRight: Op.strictRight,
  $noExtendRight: Op.noExtendRight,
  $noExtendLeft: Op.noExtendLeft,
  $and: Op.and,
  $or: Op.or,
  $any: Op.any,
  $all: Op.all,
  $values: Op.values,
  $col: Op.col
};
20. 特殊問題處理
1. findAndCountAll 主模型一條數據,子模型3條數據,最外層count爲3,,加參數 distinct:true
2.模型關係代碼建立對了,運行總報錯,說關係沒建立對,可以將代碼換文件寫入。
21.group語句
1.  Order.sum('price', {attributes:['name'], group:'name', plain:false, having:['COUNT(?)>?', 'name', 1]}).then(function(result){
 console.log(result);
})
SELECT `name`, sum(`price`) AS `sum` FROM `orders` AS `Orders` GROUP BY name HAVING COUNT('name')>1;
2.  Order.findAll({attributes:['name', [sequelize.fn('SUM', sequelize.col('price')), 'sum']], group:'name', having:['COUNT(?)>?', 'name', 1], raw:true}).then(function(result){
 console.log(result);
})

const  datas = await ctx.model.Data.findAll({
      where: { xxx },
      group: 'groupId',
});
連接查詢及分組:
1.訂單表如下
> select * from orders;
+---------+-------------+--------+------------+---------------------+
| orderId | orderNumber | price | customerId | createdOn   |
+---------+-------------+--------+------------+---------------------+
|  1 | 00001  | 128.00 |   1 | 2016-11-25 10:12:49 |
|  2 | 00002  | 102.00 |   1 | 2016-11-25 10:12:49 |
|  3 | 00003  | 199.00 |   4 | 2016-11-25 10:12:49 |
|  4 | 00004  | 99.00 |   3 | 2016-11-25 10:12:49 |
+---------+-------------+--------+------------+---------------------+
2.客戶表結構如下:
> select * from customers;
+----+-----------+-----+---------------------+---------------------+
| id | name  | sex | birthday   | createdOn   |
+----+-----------+-----+---------------------+---------------------+
| 1 | 張小三 | 1 | 1986-01-22 08:00:00 | 2016-11-25 10:16:35 |
| 2 | 李小四 | 2 | 1987-11-12 08:00:00 | 2016-11-25 10:16:35 |
| 3 | 王小五 | 1 | 1988-03-08 08:00:00 | 2016-11-25 10:16:35 |
| 4 | 趙小六 | 1 | 1989-08-11 08:00:00 | 2016-11-25 10:16:35 |
+----+-----------+-----+---------------------+---------------------+


 select c.name, SUM(o.price) AS sum from customers AS c INNER JOIN orders AS o ON o.customerId =c.id GROUP BY c.name;

 var include = [{
 model: Customer,
 required: true,
 attributes: ['name'],
}]
Order.findAll({include:include, attributes:[[sequelize.fn('SUM', sequelize.col('price')), 'sum']], group:'Customer.name', having:['COUNT(?)>?', 'name', 1], raw:true, rollup:true}).then(function(result){
 console.log(result);
})// raw:true ,Set this to true if you don't have a model definition for your query.


  Table.findAll({
   attributes: ['column1', 
     sequelize.fn('count', sequelize.col('column2'))], 
   group: ["Table.column1"]
 }).then(function (result) { });
22.Sequelize Aggregate Functions (MIN, MAX, SUM, COUNT, etc.) Examples
Sometimes you may need to use aggregate functions when fetching data from database, such as SUM, COUNT, MIN, MAX, etc. In this tutorial, I'm going to give some examples of how to use aggregate functions with Sequelize.js.

22.1 Database Models and Assocations
For this tutorial, first I define two simple models Item and SaleItem. Each models represent a real table in the database. Item stores the details of items. SaleItem stores data of item sales, with each record represents a sale for an item. For each sales, user can buy multiple amounts of an item, stored in amount column.

(adsbygoogle = window.adsbygoogle || []).push({});

models/Item.js

 const mappings = {
    id: {
      type: Sequelize.UUID,
      primaryKey: true,
      defaultValue: Sequelize.DataTypes.UUIDV4,
    },
    name: {
      type: Sequelize.TEXT,
      allowNull: false,
    },
    stock: {
      type: Sequelize.INTEGER,
      allowNull: false,
    },
    price: {
      type: Sequelize.DECIMAL,
      allowNull: false,
    },
    active: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: true,
    },
  };
models/SaleItem.js

const mappings = {
    id: {
      type: Sequelize.UUID,
      primaryKey: true,
      defaultValue: Sequelize.DataTypes.UUIDV4,
    },
    itemId: {
      type: Sequelize.UUID,
      allowNull: false,
    },
    itemPrice: {
      type: Sequelize.TEXT,
      allowNull: false,
    },
    amount: {
      type: Sequelize.INTEGER,
      allowNull: false,
    },
    cancelled: {
      type: Sequelize.BOOLEAN,
      defaultValue: false,
    },
  };
A SaleItem record belongs to an Item record and each Item may have multiple SaleItem records. We need to define the association.

(adsbygoogle = window.adsbygoogle || []).push({});

models/associations.js

  const Item = require('./Item').getModel();
  const SalesItem = require('./SaleItem').getModel();

  SalesItem.belongsTo(Item, { foreignKey: 'itemId', targetKey: 'id' });
  Item.hasMany(SalesItem, { foreignKey: 'itemId', targetKey: 'id' });
22.2 MIN Example
In order to find the price of the cheapest item, we can use MIN clause on price column of `Item` table.

exports.getMinPrice = () => Item.findAll({
    attributes: [[sequelize.fn('min', sequelize.col('price')), 'minPrice']],
  });
It generates the following query.

  SELECT min("price") AS "minPrice" FROM "Items" AS "Item";
The above example returns result in the following format.

 [ Item {
      dataValues: { minPrice: '5000000' },
      _previousDataValues: { minPrice: '5000000' },
      _changed: {},
      _modelOptions: 
       { timestamps: true,
         validate: {},
         freezeTableName: false,
         underscored: false,
         underscoredAll: false,
         paranoid: false,
         rejectOnEmpty: false,
         whereCollection: null,
         schema: null,
         schemaDelimiter: '',
         defaultScope: {},
         scopes: [],
         indexes: [Array],
         name: [Object],
         omitNull: false,
         sequelize: [Object],
         hooks: [Object],
         uniqueKeys: {} },
      _options: 
       { isNewRecord: false,
         _schema: null,
         _schemaDelimiter: '',
         raw: true,
         attributes: [Array] },
      __eagerlyLoadedAssociations: [],
      isNewRecord: false } ]
To make the result more readable, add raw: true as the argument.

exports.getMinPrice = () => Item.findAll({
    attributes: [[sequelize.fn('min', sequelize.col('price')), 'minPrice']],
    raw: true,
});
(adsbygoogle = window.adsbygoogle || []).push({});

Here's the result with raw: true.

 [ { minPrice: '5000000' } ]
22.3 MAX Example
The query for finding the price of the most expensive item is very similar to the query for finding the price of the cheapest item, just replace MIN with MAX

exports.getMaxPrice = () => Item.findAll({
    attributes: [[sequelize.fn('max', sequelize.col('price')), 'maxPrice']],
    raw: true,
});
It generates the following query.

  SELECT max("price") AS "maxPrice" FROM "Items" AS "Item";
22.4 COUNT Example
Using COUNT clause, we can find how many times each items have been sold. This is not the total number of item sold. In other word, we ignore the value of amount column. For this case, we simply count how many times an item appear in the SaleItem table

(adsbygoogle = window.adsbygoogle || []).push({});

 exports.getItemSaleCount = () => SaleItem.findAll({
    attributes: ['itemId', [sequelize.fn('count', sequelize.col('itemId')), 'count']],
    group : ['SaleItem.itemId'],
    raw: true,
    order: sequelize.literal('count DESC')
  });
It generates the following query.

  SELECT "itemId", count("itemId") AS "count" FROM "SaleItems" AS "SaleItem" GROUP BY "SaleItem"."itemId" ORDER BY count DESC;
22.5 SUM Example
If we want to get the list of best seller items, we need to sum up the value of amount column by using SUM clause.

exports.getBestSellerItems = () => SaleItem.findAll({
    attributes: ['itemId', [sequelize.fn('sum', sequelize.col('amount')), 'total']],
    group : ['SaleItem.itemId'],
    raw: true,
    order: sequelize.literal('total DESC')
  });
It generates the following query.

  SELECT "itemId", sum("amount") AS "total" FROM "SaleItems" AS "SaleItem" GROUP BY "SaleItem"."itemId" ORDER BY total DESC;
22.6 Aggregate + Populate Example
Like the previous example, but now we also populate the Item detail.

  exports.getBestSellerItems = () => SaleItem.findAll({
    attributes: [[sequelize.fn('sum', sequelize.col('amount')), 'total']],
    include : [
      {
        model : Item,
      }
    ],
    group : ['Item.id'],
    raw: true,
    order: sequelize.literal('total DESC')
  });
It generates the following query.

  SELECT sum("amount") AS "total", "Item"."id" AS "Item.id", "Item"."name" AS "Item.name", "Item"."stock" AS "Item.stock", "Item"."price" AS "Item.price", "Item"."active" AS "Item.active", "Item"."createdAt" AS "Item.createdAt", "Item"."updatedAt" AS "Item.updatedAt" FROM "SaleItems" AS "SaleItem" LEFT OUTER JOIN "Items" AS "Item" ON "SaleItem"."itemId" = "Item"."id" GROUP BY "Item"."id" ORDER BY total DESC;
That's how to use aggregate functions in Sequelize.js

23.在模型中沒有定義關聯時
1. include[ {Sequelize.literal( ' INNER JOIN user_report reports ON user.id = reports.user_id' )} ]
2. bank.findAll({
    include: [{
        model: account,
        required: false,
        on: {
            bank_name: Sequelize.col('bank.name')
        }
    }]
})
生成的sql: select * from bank left outer join account  on account.bank_name = bank.name
24.fn/col/literal函數應用
1.fn/col:    attributes: [
            [fn("concat", `${imgPre}`, col("imgPath")), "imgPath"],
            ["imgPath", "key"],
          ],
2.literal:
       await ctx.service.class.findAll({
            where: {
                numberOfPeople: {
                    [Op.lt]: literal('classroom.count')
                },
            },
            include: [{
                model: Classroom, as: 'classroom', attributes: ['count']
            }]
        });
25.case...when
var query = {
  attributes: [
    'userId',
    [Sequelize.literal(`MAX(CASE Type WHEN 'Employee' THEN Rate ELSE 0 END)`), 'Employee'],
    [Sequelize.literal(`MAX(CASE Type WHEN 'School' THEN Rate ELSE 0 END)`), 'School'],
    [Sequelize.literal(`MAX(CASE Type WHEN 'Public' THEN Rate ELSE 0 END)`), 'Public'],
    [Sequelize.literal(`MAX(CASE Type WHEN 'Other' THEN Rate ELSE 0 END)`), 'Other'],
  ],
  where: {
    user: userId,
    Type: ['Employee', 'School', 'Public', 'Other'],
  },
  group: ['userId'],
  raw: true
};
models.invoice.findAll(query).then(result => {
  console.log(result);
});
26.literal總結
1.指定列增加值
在 Sequelize 中要實現:
UPDATE user SET age=age + 1 WHERE number > 10;
可以通過 Model.update() 並藉助 sequelize 中的頂級方法 sequelize.literal() 來實現:
User.update(
  { age: sequelize.literal("age +1") },
  { where: { number: { $gt: 10 } } }
);
2.DISTINCT
在 Sequelize 中要實現:
SELECT COUNT(DISTINCT group) FROM user WHERE number > 10;
User.findAll({
  where: { number: { $gt: 10 } },
  attributes: [[sequelize.literal("COUNT(DISTINCT(group))"), "count"]],
}).then(function (list) {
  console.log(list[0].count);
});

 本文來自官網和網絡資源整理,,希望可以幫助到大家。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章