Skip to content

Latest commit

 

History

History
138 lines (107 loc) · 3.96 KB

Mongoose 数组.md

File metadata and controls

138 lines (107 loc) · 3.96 KB

Mongoose 数组

Mongoose 的 Array使用额外的 Mongoose 功能扩展了普通的 JavaScript 数组。

例如,假设您有一个带有 tags 数组的 BlogPost 模型骨架:

const blogPostSchema = new mongoose.Schema({
  title: String,
  tags: [String]
})

当您创建一个新 BlogPost 文档时,tags 属性是普通 JavaScript 数组类的一个实例。但它也有一些特殊的性质。

const blogPostSchema = Schema(
  {
    title: String,
    tags: [String]
  },
  { versionKey: false }
)
const BlogPost = mongoose.model('BlogPost', blogPostSchema)

const doc = new BlogPost({
  title: 'Intro to JavaScript',
  tags: ['programming']
})

Array.isArray(doc.tags) // true
doc.tags.isMongooseArray // true

例如,Mongoose 截取 push()tags 数组的调用,当你 save() 文档时,它足够聪明地使用 $push 更新文档。

mongoose.set('debug', true)

doc.tags.push('web development')
// 由于 debug 模式,将打印:
// Mongoose: blogposts.updateOne({ _id: ObjectId(...) }, { '$push': { tags: { '$each': [ 'web development' ] } } }, { session: null })
await doc.save()

文档数组

tags 示例是一个基元数组。Mongoose 还支持子文档数组。下面是如何定义 members 数组的方法,每个数组都有 firstNamelastName 属性。

const groupSchema = new mongoose.Schema({
  name: String,
  members: [{ firstName: String, lastName: String }]
})

doc.members 是一个普通 JavaScript 数组的实例,因此它具有所有常用函数,例如 slice()filter()。但它也有一些特定于 Mongoose 的功能。

const groupSchema = new mongoose.Schema({
  name: String,
  members: [{ firstName: String, lastName: String }]
})
const Group = mongoose.model('Group', groupSchema)

const doc = new Group({
  title: 'Jedi Order',
  members: [{ firstName: 'Luke', lastName: 'Skywalker' }]
})

Array.isArray(doc.members) // true
doc.members.isMongooseArray // true
doc.members.isMongooseDocumentArray // true

例如,如果您设置第 0 个成员的 firstName,Mongoose 将在调用 save() 时将其转换为 member.0.firstName 上的集合。

const groupSchema = Schema(
  {
    name: String,
    members: [{ firstName: String, lastName: String }]
  },
  { versionKey: false }
)
const Group = mongoose.model('Group', groupSchema)

const doc = new Group({
  title: 'Jedi Order',
  members: [{ firstName: 'Luke', lastName: 'Skywalker' }]
})
await doc.save()

mongoose.set('debug', true)

doc.members[0].firstName = 'Anakin'
// Mongoose: groups.updateOne({ _id: ObjectId("...") }, { '$set': { 'members.0.firstName': 'Anakin' } }, { session: null })
await doc.save()

设置数组索引时的注意事项

Mongoose 在直接设置数组索引方面存在一个已知问题。例如,如果您设置了 doc.tags[0],Mongoose 更改跟踪将不会获取该更改。

const blogPostSchema = Schema(
  {
    title: String,
    tags: [String]
  },
  { versionKey: false }
)
const BlogPost = mongoose.model('BlogPost', blogPostSchema)

const doc = new BlogPost({
  title: 'Intro to JavaScript',
  tags: ['programming']
})
await doc.save()

// 此更改不会在数据库中结束!
doc.tags[0] = 'JavaScript'
await doc.save()

const fromDb = await BlogPost.findOne({ _id: doc._id })
console.log(fromDb.tags) // ['programming']

为了解决这个问题,您需要使用 markModified()方法或在数组元素上显式调用 MongooseArray.set() 来通知 Mongoose 的更改跟踪,如下所示。

// 这种改变是有效的。set() 是 Mongoose 数组上触发更改跟踪的一种特殊方法。
doc.tags.set(0, 'JavaScript')
await doc.save()

const fromDb = await BlogPost.findOne({ _id: doc._id })
console.log(fromDb.tags) // ['JavaScript']