iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 15
1

今天回頭來介紹 Mongoose 的基本用法。


Schema Model Instance

建立 Model ,依照 Model 中設定的 Schema 建立許多 Instances。
Mongoose
圖片來源

連結上 MongoDB

  • mongoose.connect():用來連上 database(MongoDB)。
mongoose.connect('URL', { useNewUrlParser: true })
  • mongoose.connection:取得 mongoose.connect() 連上的默認 Connection object。
const db = mongoose.connection
  • mongoose.createConnection():用來連結第二個以上的 database。
    功能等於: mongoose.connect()mongoose.connection
const db = mongoose.createConnection('URL', { useNewUrlParser: true })
  • 備註:如果你的 Mongoose 版本>= 3.1.0,改寫成如下,以解決錯誤訊息:
mongoose.connect('URL', { useNewUrlParser: true, useUnifiedTopology: true })

建立 Models

*每個 model 會 map 到 MongoDB 上生成一群文件的 collection *

  • Schema constructor:用new來建立你的 schema instance,在{ }中設定骨架樣式(Collection 中文件的樣式)。
    • 還有許多設定的型態,請參照文件
    • 大多數是在 "名稱:" 或 “type:”,對其作解釋,只有三個除外:ObjectId、Mixed、[]。
    • value 也可以一個 設定規則的object 表示。
const SchemaName = new Schema({
    a_string: String,  // a_string 的值的型態為 String
    a_date: Date       // a_date 的值的型態為 Date
}) 
  • mongoose.model():用以建立 Model。
    (參數1:欲創建的 collection 名稱 / 參數2:欲使用的 Schema)
const ModelName = mongoose.model('CollectionName', SchemaName )
  • 內建驗證器常見的如下:
    • 所有型態:required(設定為必填)
    • Numbers:minmax(最小最大值)
    • Strings:
      • enum:允許使用的字串集合。
      • match:需符合 regular expression。
      • maxlengthminlength:最大最小長度
const breakfastSchema = new Schema({
  // eggs - 可填的value為數字型態,範圍在6~12,小於6會顯示'Too few eggs',沒填會顯示'Why no eggs?'
  eggs: {
    type: Number,
    min: [6, 'Too few eggs'],
    max: 12,
    required: [true, 'Why no eggs?']
  },
  // drink - 可填的value為字串型態,只可填入Coffee、Tea、Water
  drink: {
    type: String,
    enum: ['Coffee', 'Tea', 'Water']
  }
})
  • Virtual 屬性:以建立來方便使用,但不會存進 MongoDB。(例如 full name屬性、以 _id 生成特有 URL。)
  • methods:
    • instance methods:新增於所有 instance。
    • static methods:新增於 Model。

使用 Models

新增及修改 documents

  • save():儲存進 database(MongoDb)
// 以 SomeModel 建立新的 instance
const awesome_instance = new SomeModel({ name: 'awesome' })

// 檢查是否有錯誤,無誤則儲存這個 instance 至 database
awesome_instance.save(function (err) {
  if (err) return handleError(err)
})
  • create()newsave() 建立新的 instance 並儲存。
// 
SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) {
  if (err) return handleError(err)
})
  • 可使用如 .name 來更改其值,改完後用 save()update()儲存。
awesome_instance.name = "New cool name"
awesome_instance.save(function (err) {
   if (err) return handleError(err) 
})

搜尋

  • 可用搜尋的方法並以 JSON 型式書寫篩選條件,來進行搜尋。
// 找出所有網球選手,並列出姓名、年齡
Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) {
  if (err) return handleError(err);
})
  • 也可以不放 callback ,則會回傳一個 query object ,可用來設定客製化 query
    ,再以 exec() 執行
const query = Athlete.find({ 'sport': 'Tennis' })
// 選擇 姓名、年齡 輸出
query.select('name age')
// 限制為5個結果
query.limit(5)
// 以年齡排列
query.sort({ age: -1 })
// 以 `exec()` 執行
query.exec(function (err, athletes) {if (err) return handleError(err)})
  • 也可用 where() 來設定條件,並用 . 連接起來。
Athlete.
  find().
  where('sport').equals('Tennis'). // 網球選手
  where('age').gt(17).lt(50).      // 17~50歲
  limit(5).
  sort({ age: -1 }).
  select('name age').
  exec(callback)
  • 只取得一個配對結果的方法:
    • findById():以指定id查檔
    • findOne():只列出第一個符合配對的檔案
    • findByIdAndRemove()等:查檔後進行更新或刪除。

建立文件間的關聯 - population

  • ObjectId:用來指向特定ID的內容。
  • ref:用來指定從特定 model 取得內容來源。
  • populate():從該field指定的ID取得資訊。
const authorSchema = Schema({
  name: String,
  stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
})
const storySchema = Schema({
// author 的值設定為:從 Author 這個 model 中,指向某特定ID的內容
  author: { type: Schema.Types.ObjectId, ref: 'Author' },
  title: String
})
const Story = mongoose.model('Story', storySchema)
const Author = mongoose.model('Author', authorSchema)

const bob = new Author({ name: 'Bob Smith' })
bob.save(function (err) {
  if (err) return handleError(err)
  // 建立一個 story 使其作者指向 bob 的 id 的內容
  const story = new Story({
    title: 'Bob goes sledding',
    author: bob._id  // 在前面建立 bob 時已自動生成自己的 id
  })
  story.save(function (err) {if (err) return handleError(err)})
})
  • 取得 story 的 author 資訊:
Story
  .findOne({ title: 'Bob goes sledding' })
  // 使用 populate() 取得 Story 的 author 中所指向的 ID 內容
  .populate('author') 
  .exec(function (err, story) {
    if (err) return handleError(err)
    console.log('The author is %s', story.author.name)
    // 在此即可以 story.author.name 直接取得該ID的 Author 中的 name 內容
  })
  • 取得 author 的 story 資訊:
    1. 再次以上述方法設定 Author 中的 stories 指向的 ID
    2. 直接以下列方式取得該 Author 的所有 stories(此方法可以只設定一次ID就獲取雙向的資訊。)
Story
  .find({ author: bob._id })
  .exec(function (err, stories) {
    if (err) return handleError(err)
  })

建議將每個 model 都做成一個獨立的 module ,以獨立的文檔寫成。


附上一篇覺得可以參考的 Mongoose 文章


上一篇
Day 14- 190930學習筆記 建立Database (Mongoose/MongoDb)
下一篇
Day 16- 191002學習筆記 Express Route 設置
系列文
轉職道上的萌芽人生 − 自學程式開發ing30

尚未有邦友留言

立即登入留言