Sequelize官方中文文檔 3. Model usage - 模型使用

Sequelize官方GitHub:https://github.com/sequelize/sequelize
Sequelize官方中文文檔:https://github.com/demopark/sequelize-docs-Zh-CN
Sequelize官方英文文檔:http://docs.sequelizejs.com/

Model usage - 模型使用

數(shù)據(jù)檢索/查找器

Finder 方法旨在從數(shù)據(jù)庫查詢數(shù)據(jù)。 他們 返回簡單的對(duì)象,而是返回模型實(shí)例。 因?yàn)?finder 方法返回模型實(shí)例直晨,您可以按照 實(shí)例 的文檔中所述坡氯,為結(jié)果調(diào)用任何模型實(shí)例成員且叁。

在本文中,我們將探討 finder 方法可以做什么:

find - 搜索數(shù)據(jù)庫中的一個(gè)特定元素

// 搜索已知的ids
Project.findById(123).then(project => {
  // project 將是 Project的一個(gè)實(shí)例掰盘,并具有在表中存為 id 123 條目的內(nèi)容欠橘。
  // 如果沒有定義這樣的條目矩肩,你將獲得null
})

// 搜索屬性
Project.findOne({ where: {title: 'aProject'} }).then(project => {
  // project 將是 Projects 表中 title 為 'aProject'  的第一個(gè)條目 || null
})


Project.findOne({
  where: {title: 'aProject'},
  attributes: ['id', ['name', 'title']]
}).then(project => {
  // project 將是 Projects 表中 title 為 'aProject'  的第一個(gè)條目 || null
  // project.title 將包含 project 的 name
})

findOrCreate - 搜索特定元素或創(chuàng)建它(如果不可用)

方法 findOrCreate 可用于檢查數(shù)據(jù)庫中是否已存在某個(gè)元素。 如果是這種情況简软,則該方法將生成相應(yīng)的實(shí)例蛮拔。 如果元素不存在,將會(huì)被創(chuàng)建痹升。

如果是這種情況建炫,則該方法將導(dǎo)致相應(yīng)的實(shí)例。 如果元素不存在疼蛾,將會(huì)被創(chuàng)建肛跌。

假設(shè)我們有一個(gè)空的數(shù)據(jù)庫,一個(gè) User 模型有一個(gè) usernamejob察郁。

User
  .findOrCreate({where: {username: 'sdepold'}, defaults: {job: 'Technical Lead JavaScript'}})
  .spread((user, created) => {
    console.log(user.get({
      plain: true
    }))
    console.log(created)

    /*
    findOrCreate 返回一個(gè)包含已找到或創(chuàng)建的對(duì)象的數(shù)組衍慎,找到或創(chuàng)建的對(duì)象和一個(gè)布爾值,如果創(chuàng)建一個(gè)新對(duì)象將為true皮钠,否則為false稳捆,像這樣:

    [ {
        username: 'sdepold',
        job: 'Technical Lead JavaScript',
        id: 1,
        createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
        updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
      },
      true ]

在上面的例子中,".spread" 將數(shù)組分成2部分麦轰,并將它們作為參數(shù)傳遞給回調(diào)函數(shù)乔夯,在這種情況下將它們視為 "user" 和 "created" 。(所以“user”將是返回?cái)?shù)組的索引0的對(duì)象款侵,并且 "created" 將等于 "true"末荐。)
    */
  })

代碼創(chuàng)建了一個(gè)新的實(shí)例。 所以當(dāng)我們已經(jīng)有一個(gè)實(shí)例了 ...

User.create({ username: 'fnord', job: 'omnomnom' })
  .then(() => User.findOrCreate({where: {username: 'fnord'}, defaults: {job: 'something else'}}))
  .spread((user, created) => {
    console.log(user.get({
      plain: true
    }))
    console.log(created)

    /*
    在這個(gè)例子中新锈,findOrCreate 返回一個(gè)如下的數(shù)組:
    [ {
        username: 'fnord',
        job: 'omnomnom',
        id: 2,
        createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
        updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
      },
      false
    ]
    由findOrCreate返回的數(shù)組通過 ".spread" 擴(kuò)展為兩部分甲脏,并且這些部分將作為2個(gè)參數(shù)傳遞給回調(diào)函數(shù),在這種情況下將其視為 "user" 和 "created" 妹笆。(所以“user”將是返回?cái)?shù)組的索引0的對(duì)象块请,并且 "created" 將等于 "false"。)
    */
  })

...現(xiàn)有條目將不會(huì)更改拳缠。 看到第二個(gè)用戶的 "job"负乡,并且實(shí)際上創(chuàng)建操作是假的。

findAndCountAll - 在數(shù)據(jù)庫中搜索多個(gè)元素脊凰,返回?cái)?shù)據(jù)和總計(jì)數(shù)

這是一個(gè)方便的方法抖棘,它結(jié)合了 findAllcount(見下文),當(dāng)處理與分頁相關(guān)的查詢時(shí)狸涌,這是有用的切省,你想用 limitoffset 檢索數(shù)據(jù),但也需要知道總數(shù)與查詢匹配的記錄數(shù):

處理程序成功將始終接收具有兩個(gè)屬性的對(duì)象:

  • count - 一個(gè)整數(shù)帕胆,總數(shù)記錄匹配where語句和關(guān)聯(lián)的其它過濾器
  • rows - 一個(gè)數(shù)組對(duì)象朝捆,記錄在limit和offset范圍內(nèi)匹配where語句和關(guān)聯(lián)的其它過濾器,
Project
  .findAndCountAll({
     where: {
        title: {
          [Op.like]: 'foo%'
        }
     },
     offset: 10,
     limit: 2
  })
  .then(result => {
    console.log(result.count);
    console.log(result.rows);
  });

它支持 include懒豹。 只有標(biāo)記為 required 的 include 將被添加到計(jì)數(shù)部分:

假設(shè)您想查找附有個(gè)人資料的所有用戶:

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

因?yàn)?Profile 的 include 有 required 設(shè)置芙盘,這將導(dǎo)致內(nèi)部連接驯用,并且只有具有 profile 的用戶將被計(jì)數(shù)。 如果我們從 include 中刪除required儒老,那么有和沒有 profile 的用戶都將被計(jì)數(shù)蝴乔。 在include中添加一個(gè) where 語句會(huì)自動(dòng)使它成為 required:

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

上面的查詢只會(huì)對(duì)具有 active profile 的用戶進(jìn)行計(jì)數(shù),因?yàn)樵趯?where 語句添加到 include 時(shí)驮樊,required 被隱式設(shè)置為 true薇正。

傳遞給 findAndCountAll 的 options 對(duì)象與 findAll 相同(如下所述)。

findAll - 搜索數(shù)據(jù)庫中的多個(gè)元素

// 找到多個(gè)條目
Project.findAll().then(projects => {
  // projects 將是所有 Project 實(shí)例的數(shù)組
})

// 也可以:
Project.all().then(projects => {
  // projects 將是所有 Project 實(shí)例的數(shù)組
})

// 搜索特定屬性 - 使用哈希
Project.findAll({ where: { name: 'A Project' } }).then(projects => {
  // projects將是一個(gè)具有指定 name 的 Project 實(shí)例數(shù)組
})

// 在特定范圍內(nèi)進(jìn)行搜索
Project.findAll({ where: { id: [1,2,3] } }).then(projects => {
  // projects將是一系列具有 id 1,2 或 3 的項(xiàng)目
  // 這實(shí)際上是在做一個(gè) IN 查詢
})

Project.findAll({
  where: {
    id: {
      [Op.and]: {a: 5},           // 且 (a = 5)
      [Op.or]: [{a: 5}, {a: 6}],  // (a = 5 或 a = 6)
      [Op.gt]: 6,                // id > 6
      [Op.gte]: 6,               // id >= 6
      [Op.lt]: 10,               // id < 10
      [Op.lte]: 10,              // id <= 10
      [Op.ne]: 20,               // id != 20
      [Op.between]: [6, 10],     // 在 6 和 10 之間
      [Op.notBetween]: [11, 15], // 不在 11 和 15 之間
      [Op.in]: [1, 2],           // 在 [1, 2] 之中
      [Op.notIn]: [1, 2],        // 不在 [1, 2] 之中
      [Op.like]: '%hat',         // 包含 '%hat'
      [Op.notLike]: '%hat',       // 不包含 '%hat'
      [Op.iLike]: '%hat',         // 包含 '%hat' (不區(qū)分大小寫)  (僅限 PG)
      [Op.notILike]: '%hat',      // 不包含 '%hat'  (僅限 PG)
      [Op.overlap]: [1, 2],       // && [1, 2] (PG數(shù)組重疊運(yùn)算符)
      [Op.contains]: [1, 2],      // @> [1, 2] (PG數(shù)組包含運(yùn)算符)
      [Op.contained]: [1, 2],     // <@ [1, 2] (PG數(shù)組包含于運(yùn)算符)
      [Op.any]: [2,3],            // 任何數(shù)組[2, 3]::INTEGER (僅限 PG)
    },
    status: {
      [Op.not]: false,           // status 不為 FALSE
    }
  }
})

復(fù)合過濾 / OR / NOT 查詢

你可以使用多層嵌套的 AND囚衔,OR 和 NOT 條件進(jìn)行一個(gè)復(fù)合的 where 查詢挖腰。 為了做到這一點(diǎn),你可以使用 or 练湿, andnot 運(yùn)算符:

Project.findOne({
  where: {
    name: 'a project',
    [Op.or]: [
      { id: [1,2,3] },
      { id: { [Op.gt]: 10 } }
    ]
  }
})

Project.findOne({
  where: {
    name: 'a project',
    id: {
      [Op.or]: [
        [1,2,3],
        { [Op.gt]: 10 }
      ]
    }
  }
})

這兩段代碼將生成以下內(nèi)容:

SELECT *
FROM `Projects`
WHERE (
  `Projects`.`name` = 'a project'
   AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` > 10)
)
LIMIT 1;

not 示例:

Project.findOne({
  where: {
    name: 'a project',
    [Op.not]: [
      { id: [1,2,3] },
      { array: { [Op.contains]: [3,4,5] } }
    ]
  }
});

將生成:

SELECT *
FROM `Projects`
WHERE (
  `Projects`.`name` = 'a project'
   AND NOT (`Projects`.`id` IN (1,2,3) OR `Projects`.`array` @> ARRAY[3,4,5]::INTEGER[])
)
LIMIT 1;

用限制猴仑,偏移,順序和分組操作數(shù)據(jù)集

要獲取更多相關(guān)數(shù)據(jù)肥哎,可以使用限制宁脊,偏移,順序和分組:

// 限制查詢的結(jié)果
Project.findAll({ limit: 10 })

// 跳過前10個(gè)元素
Project.findAll({ offset: 10 })

// 跳過前10個(gè)元素贤姆,并獲取2個(gè)
Project.findAll({ offset: 10, limit: 2 })

分組和排序的語法是相同的榆苞,所以下面只用一個(gè)單獨(dú)的例子來解釋分組,而其余的則是排序霞捡。 您下面看到的所有內(nèi)容也可以對(duì)分組進(jìn)行

Project.findAll({order: 'title DESC'})
// 生成 ORDER BY title DESC

Project.findAll({group: 'name'})
// 生成 GROUP BY name

請(qǐng)注意坐漏,在上述兩個(gè)示例中,提供的字符串逐字插入到查詢中碧信,所以不會(huì)轉(zhuǎn)義列名稱赊琳。 當(dāng)你向 order / group 提供字符串時(shí),將始終如此砰碴。 如果要轉(zhuǎn)義列名躏筏,您應(yīng)該提供一個(gè)參數(shù)數(shù)組,即使您只想通過單個(gè)列進(jìn)行 order / group

something.findOne({
  order: [
    // 將返回 `name`
    ['name'],
    // 將返回 `username` DESC
    ['username', 'DESC'],
    // 將返回 max(`age`)
    sequelize.fn('max', sequelize.col('age')),
    // 將返回 max(`age`) DESC
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    // 將返回 otherfunction(`col1`, 12, 'lalala') DESC
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    // 將返回 otherfunction(awesomefunction(`col`)) DESC呈枉,這個(gè)嵌套是可以無限的趁尼!
    [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
  ]
})

回顧一下,order / group數(shù)組的元素可以是以下內(nèi)容:

  • String - 將被引用
  • Array - 第一個(gè)元素將被引用猖辫,第二個(gè)將被逐字地追加
  • Object -
    • raw 將被添加逐字引用
    • 如果未設(shè)置 raw酥泞,一切都被忽略,查詢將失敗
  • Sequelize.fn 和 Sequelize.col 返回函數(shù)和引用的列名

原始查詢

有時(shí)候啃憎,你可能會(huì)期待一個(gè)你想要顯示的大量數(shù)據(jù)集芝囤,而無需操作。 對(duì)于你選擇的每一行,Sequelize 創(chuàng)建一個(gè)具有更新悯姊,刪除和獲取關(guān)聯(lián)等功能的實(shí)例羡藐。如果您有數(shù)千行,則可能需要一些時(shí)間悯许。 如果您只需要原始數(shù)據(jù)仆嗦,并且不想更新任何內(nèi)容,您可以這樣做來獲取原始數(shù)據(jù)岸晦。

// 你期望從數(shù)據(jù)庫的一個(gè)巨大的數(shù)據(jù)集,
// 并且不想花時(shí)間為每個(gè)條目構(gòu)建DAO欧啤?
// 您可以傳遞一個(gè)額外的查詢參數(shù)來取代原始數(shù)據(jù):
Project.findAll({ where: { ... }, raw: true })

count - 計(jì)算數(shù)據(jù)庫中元素的出現(xiàn)次數(shù)

還有一種數(shù)據(jù)庫對(duì)象計(jì)數(shù)的方法:

Project.count().then(c => {
  console.log("There are " + c + " projects!")
})

Project.count({ where: {'id': {[Op.gt]: 25}} }).then(c => {
  console.log("There are " + c + " projects with an id greater than 25.")
})

max - 獲取特定表中特定屬性的最大值

這里是獲取屬性的最大值的方法:

/*
   我們假設(shè)3個(gè)具有屬性年齡的對(duì)象睛藻。
   第一個(gè)是10歲启上,
   第二個(gè)是5歲,
   第三個(gè)是40歲店印。
*/
Project.max('age').then(max => {
  // 將返回 40
})

Project.max('age', { where: { age: { [Op.lt]: 20 } } }).then(max => {
  // 將會(huì)是 10
})

min - 獲取特定表中特定屬性的最小值

這里是獲取屬性的最小值的方法:

/*
   我們假設(shè)3個(gè)具有屬性年齡的對(duì)象冈在。
   第一個(gè)是10歲,
   第二個(gè)是5歲按摘,
   第三個(gè)是40歲包券。
*/
Project.min('age').then(min => {
  // 將返回 5
})

Project.min('age', { where: { age: { [Op.gt]: 5 } } }).then(min => {
  // 將會(huì)是 10
})

sum - 特定屬性的值求和

為了計(jì)算表的特定列的總和,可以使用“sum”方法炫贤。

/*
   我們假設(shè)3個(gè)具有屬性年齡的對(duì)象溅固。
   第一個(gè)是10歲,
   第二個(gè)是5歲兰珍,
   第三個(gè)是40歲侍郭。
*/
Project.sum('age').then(sum => {
  // 將返回 55
})

Project.sum('age', { where: { age: { [Op.gt]: 5 } } }).then(sum => {
  // 將會(huì)是 50
})

預(yù)加載

當(dāng)你從數(shù)據(jù)庫檢索數(shù)據(jù)時(shí),也想同時(shí)獲得與之相關(guān)聯(lián)的查詢掠河,這被稱為預(yù)加載亮元。這個(gè)基本思路就是當(dāng)你調(diào)用 findfindAll 時(shí)使用 include 屬性。讓我們假設(shè)以下設(shè)置:

const User = sequelize.define('user', { name: Sequelize.STRING })
const Task = sequelize.define('task', { name: Sequelize.STRING })
const Tool = sequelize.define('tool', { name: Sequelize.STRING })

Task.belongsTo(User)
User.hasMany(Task)
User.hasMany(Tool, { as: 'Instruments' })

sequelize.sync().then(() => {
  // 這是我們繼續(xù)的地方 ...
})

首先唠摹,讓我們用它們的關(guān)聯(lián) user 加載所有的 task爆捞。

Task.findAll({ include: [ User ] }).then(tasks => {
  console.log(JSON.stringify(tasks))

  /*
    [{
      "name": "A Task",
      "id": 1,
      "createdAt": "2013-03-20T20:31:40.000Z",
      "updatedAt": "2013-03-20T20:31:40.000Z",
      "userId": 1,
      "user": {
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z"
      }
    }]
  */
})

請(qǐng)注意,訪問者(結(jié)果實(shí)例中的 User 屬性)是單數(shù)形式勾拉,因?yàn)殛P(guān)聯(lián)是一對(duì)一的煮甥。

接下來的事情:用多對(duì)一的關(guān)聯(lián)加載數(shù)據(jù)!

User.findAll({ include: [ Task ] }).then(users => {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "tasks": [{
        "name": "A Task",
        "id": 1,
        "createdAt": "2013-03-20T20:31:40.000Z",
        "updatedAt": "2013-03-20T20:31:40.000Z",
        "userId": 1
      }]
    }]
  */
})

請(qǐng)注意藕赞,訪問者(結(jié)果實(shí)例中的 Tasks 屬性)是復(fù)數(shù)形式苛秕,因?yàn)殛P(guān)聯(lián)是多對(duì)一的。

如果關(guān)聯(lián)是別名的(使用 as 參數(shù))找默,則在包含模型時(shí)必須指定此別名艇劫。 注意用戶的 Tool 如何被別名為 Instruments。 為了獲得正確的權(quán)限,您必須指定要加載的模型以及別名:

User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(users => {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1
      }]
    }]
  */
})

您還可以通過指定與關(guān)聯(lián)別名匹配的字符串來包含別名:

User.findAll({ include: ['Instruments'] }).then(users => {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1
      }]
    }]
  */
})

User.findAll({ include: [{ association: 'Instruments' }] }).then(users => {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1
      }]
    }]
  */
})

當(dāng)預(yù)加載時(shí)店煞,我們也可以使用 where 過濾關(guān)聯(lián)的模型蟹演。 這將返回 Tool 模型中所有與 where 語句匹配的行的User

User.findAll({
    include: [{
        model: Tool,
        as: 'Instruments',
        where: { name: { [Op.like]: '%ooth%' } }
    }]
}).then(users => {
    console.log(JSON.stringify(users))

    /*
      [{
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],

      [{
        "name": "John Smith",
        "id": 2,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],
    */
  })

當(dāng)使用 include.where 過濾一個(gè)預(yù)加載的模型時(shí)顷蟀,include.required 被隱式設(shè)置為 true酒请。 這意味著內(nèi)部聯(lián)接完成返回具有任何匹配子項(xiàng)的父模型。

使用預(yù)加載模型的頂層 WHERE

將模型的 WHERE 條件從 ON 條件的 include 模式移動(dòng)到頂層鸣个,你可以使用 '$nested.column$' 語法:

User.findAll({
    where: {
        '$Instruments.name$': { [Op.iLike]: '%ooth%' }
    },
    include: [{
        model: Tool,
        as: 'Instruments'
    }]
}).then(users => {
    console.log(JSON.stringify(users));

    /*
      [{
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],

      [{
        "name": "John Smith",
        "id": 2,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],
    */

包括所有

要包含所有屬性羞反,您可以使用 all:true 傳遞單個(gè)對(duì)象:

User.findAll({ include: [{ all: true }]});

包括軟刪除的記錄

如果想要加載軟刪除的記錄,可以通過將 include.paranoid 設(shè)置為 false 來實(shí)現(xiàn)

User.findAll({
    include: [{
        model: Tool,
        where: { name: { [Op.like]: '%ooth%' } },
        paranoid: false // query and loads the soft deleted records
    }]
});

排序預(yù)加載關(guān)聯(lián)

在一對(duì)多關(guān)系的情況下囤萤。

Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
Company.findAll({
  include: [ { model: Division, as: 'Div' } ],
  order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
});
Company.findAll({
  include: [ { model: Division, as: 'Div' } ],
  order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ]
});
Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, Department, 'name' ] ]
});

在多對(duì)多關(guān)系的情況下昼窗,您還可以通過表中的屬性進(jìn)行排序。

Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, DepartmentDivision, 'name' ] ]
});

嵌套預(yù)加載

您可以使用嵌套的預(yù)加載來加載相關(guān)模型的所有相關(guān)模型:

User.findAll({
  include: [
    {model: Tool, as: 'Instruments', include: [
      {model: Teacher, include: [ /* etc */]}
    ]}
  ]
}).then(users => {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{ // 1:M and N:M association
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1,
        "Teacher": { // 1:1 association
          "name": "Jimi Hendrix"
        }
      }]
    }]
  */
})

這將產(chǎn)生一個(gè)外連接涛舍。 但是澄惊,相關(guān)模型上的 where 語句將創(chuàng)建一個(gè)內(nèi)部連接,并僅返回具有匹配子模型的實(shí)例富雅。 要返回所有父實(shí)例掸驱,您應(yīng)該添加 required: false

User.findAll({
  include: [{
    model: Tool,
    as: 'Instruments',
    include: [{
      model: Teacher,
      where: {
        school: "Woodstock Music School"
      },
      required: false
    }]
  }]
}).then(users => {
  /* ... */
})

以上查詢將返回所有用戶及其所有樂器没佑,但只會(huì)返回與 Woodstock Music School 相關(guān)的老師毕贼。

包括所有也支持嵌套加載:

User.findAll({ include: [{ all: true, nested: true }]});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛤奢,隨后出現(xiàn)的幾起案子鬼癣,更是在濱河造成了極大的恐慌,老刑警劉巖远剩,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扣溺,死亡現(xiàn)場離奇詭異,居然都是意外死亡瓜晤,警方通過查閱死者的電腦和手機(jī)锥余,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痢掠,“玉大人驱犹,你說我怎么就攤上這事∽慊” “怎么了雄驹?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長淹辞。 經(jīng)常有香客問我医舆,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任蔬将,我火速辦了婚禮爷速,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘霞怀。我一直安慰自己惫东,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布毙石。 她就那樣靜靜地躺著廉沮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徐矩。 梳的紋絲不亂的頭發(fā)上滞时,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音丧蘸,去河邊找鬼漂洋。 笑死遥皂,一個(gè)胖子當(dāng)著我的面吹牛力喷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播演训,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼弟孟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了样悟?” 一聲冷哼從身側(cè)響起拂募,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窟她,沒想到半個(gè)月后陈症,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡震糖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年录肯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吊说。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡论咏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颁井,到底是詐尸還是另有隱情厅贪,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布雅宾,位于F島的核電站养涮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贯吓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一贬芥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宣决,春花似錦蘸劈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洼专,卻和暖如春棒掠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屁商。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國打工烟很, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜡镶。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓雾袱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親官还。 傳聞我的和親對(duì)象是個(gè)殘疾皇子芹橡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361