var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
到目前为止,我们已经创建了两个模型。我们的Person 模型有stories字段设置为ObjectIds数组。ref 选项告诉Mongoose哪个模型中中使用 population,在我们的案例 Story 模型。所有的_ids我们存储的必须是 Story 模型的_ids。我们还声明 Story 的_creator属性作为数字型,和 _id类型相同用在personSchema中。这是非常重要的匹配 _id类型到 ref 类型。
注:ObjectId,Number,String,和Buffer都是作为refs有效的类型。
Saving refs
引用其他文件保存的工作方式相同,通常保存属性,只是分配的_id值:
var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });
aaron.save(function (err) {
if (err) return handleError(err);
var story1 = new Story({
title: "Once upon a timex.",
_creator: aaron._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
});
Population
到目前为止,我们还没有做任何不同的事情。我们只是创造了一个 Person 和一个 Story 。现在让我们使用查询生成器看一下填充story的_creator。
Story
.findOne({ title: 'Once upon a timex.' })
.populate('_creator')
.exec(function (err, story) {
if (err) return handleError(err);
console.log('The creator is %s', story._creator.name);
// prints "The creator is Aaron"
});
Story
.findOne({ title: /timex/i })
.populate('_creator', 'name') // only return the Persons name
.exec(function (err, story) {
if (err) return handleError(err);
console.log('The creator is %s', story._creator.name);
// prints "The creator is Aaron"
console.log('The creators age is %s', story._creator.age);
// prints "The creators age is null'
})
`
Populating multiple paths
如果我们想在同一时间填充多个路径呢?
Story
.find(...)
.populate('fans _creator') // space delimited path names
.exec()
Person
.findOne({ name: 'Aaron' })
.populate('stories') // only works if we pushed refs to children
.exec(function (err, person) {
if (err) return handleError(err);
console.log(person);
})
User.
findOne({ name: 'Val' }).
populate({
path: 'friends',
// Get friends of friends - populate the 'friends' array for every friend
populate: { path: 'friends' }
});
Populating整个数据库
让我们说,你有一个代表事件的模式,和一个代表对话的模式。每个事件都有一个相应的会话线程。
var eventSchema = new Schema({
name: String,
// The id of the corresponding conversation
// Notice there's no ref here!
conversation: ObjectId
});
var conversationSchema = new Schema({
numMessages: Number
});
同时,假设事件和对话都存储在单独的MongoDB实例。
var db1 = mongoose.createConnection('localhost:27000/db1');
var db2 = mongoose.createConnection('localhost:27001/db2');
var Event = db1.model('Event', eventSchema);
var Conversation = db2.model('Conversation', conversationSchema);
var PersonSchema = new Schema({
name: String,
band: String
});
var BandSchema = new Schema({
name: String
});
BandSchema.virtual('members', {
ref: 'Person', // The model to use
localField: 'name', // Find people where `localField`
foreignField: 'band' // is equal to `foreignField`
});
var Person = mongoose.model('Person', personSchema);
var Band = mongoose.model('Band', bandSchema);
/**
* Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue"
* And 4 people: "Axl Rose" and "Slash" with "Guns N' Roses", and
* "Vince Neil" and "Nikki Sixx" with "Motley Crue"
*/
Band.find({}).populate('members').exec(function(error, bands) {
/* `bands.members` is now an array of instances of `Person` */
});
`