文檔一:
drawApply
= new Schema({
salesId
: { type: Schema.ObjectId, ref: 'sales' },
money
: Number,
status
: { type: Number, default: 0 },
createTime
: { type: Date, default: Date.now }
});
sales
= new Schema({
name
: { type: String, required: true, unique: true },
pwd
: String,
phone
: String,
merchant
: { type: Schema.ObjectId, ref: 'merchant' },
status
: { type: Number, default: 0 }
});
merchant
= new Schema({
name
: String,
sname
: String,
type
: String
});
表drawApply的salesId屬性指定表sales的_id,表sales的屬性merchant指定表merchant的_id。這是一種嵌套級聯的關係。
查找drawApply表的數據,並同時返回對應的sales表的數據,能夠使用下面的方法:
drawApply
.find().populate('salesId', '_id name phone merchant').sort({createTime: -1}).exec(function(err, list) {
});
返回的結果中除了drawApply表的數據外,還會包含salesId中_id,name,phone,merchant四個屬性的值。可是merchant屬性的值是以ObjectId的形式顯示的,若是想知道對應的merchant其它屬性的值,則須要使用到嵌套的populate。代碼以下:
drawApply
.find().populate({
path
: 'salesId',
select
: '_id name phone merchant',
model
: 'sales',
populate
: {
path
: 'merchant',
select
: '_id sname',
model
: 'merchant'
}).sort({createTime: -1}).exec(function(err, list) {
});
若是drawApply表中還存在其它ObjectId類型的字段,則能夠在populate方法後面繼續跟其它的populate,使用方法相同,如:
drawApply
.find().populate({
path
: 'salesId',
select
: '_id name phone merchant',
model
: 'sales',
populate
: {
path
: 'merchant',
select
: '_id sname',
model
: 'merchant'
})
.populate('approver', 'name')
.populate('operator', 'name')
.sort({createTime: -1}).exec(function(err, list) {
});
文檔二
在使用 mongoose 時,想經過一個外鍵與另外一張表創建關聯時,不知該如何簡單快捷的實現,特意去查了一下,發現了 population 這個功能,在此簡單記錄下 mongoose 的 populate 使用。
環境
參考文檔
ECMAScript 6 入門 —— Promise對象, 阮一峯
Mongoose 之 Population 使用, aikin
使用方法
我以爲參考文檔裏的那篇文章 Mongoose 之 Population 使用, aikin 寫的很詳細了,這裏爲方便看,我把它複製過來了,因此,使用方法部分基本出自上述文章.
語法
Query.populate(path, [select], [model], [match], [options])
參數 Option
path
String類型的時, 指定要填充的關聯字段,要填充多個關聯字段能夠以空格分隔。
Object類型的時,就是把 populate 的參數封裝到一個對象裏。固然也能夠是個數組。下面的例子中將會實現。
select
類型:Object或String,可選,指定填充 document 中的哪些字段。
Object類型的時,格式如: {name: 1, _id: 0},爲0表示不填充,爲1時表示填充。
String類型的時,格式如: 「name -_id」,用空格分隔字段,在字段名前加上-表示不填充。詳細語法介紹 query-select
model
類型:Model,可選,指定關聯字段的 model,若是沒有指定就會使用Schema的ref。
match
options
類型:Object,可選,指定附加的其餘查詢選項,如排序以及條數限制等等。
基本使用
數據模型
var mongoose = require('mongoose');
mongoose
.Promise = require('bluebird');
mongoose
.connect('mongodb://localhost/population');
var Schema = mongoose.Schema;
var userSchema = new Schema({
name
: String,
age
: Number,
posts
: [{type: Schema.Types.ObjectId, ref: 'post'}],
comments
: [{type: Schema.Types.ObjectId, ref: 'comment'}]
});
var User = mongoose.model('user', userSchema);
var postSchema = new Schema({
title
: String,
content
: String,
author
: {type: Schema.Types.ObjectId, ref: 'user'},
comments
: [{type: Schema.Types.ObjectId, ref: 'comment'}]
});
var Post = mongoose.model('post', postSchema);
var commentSchema = new Schema({
content
: String,
author
: {type: Schema.Types.ObjectId, ref: 'user'}
})
var Comment = mongoose.model('comment', commentSchema);
exports
.User = User;
exports
.Post = Post;
exports
.Comment = Comment;
注: ref 對應的應該是在connection中註冊過的model。
var User = mongoose.model('user', userSchema);
...
author
: {type: Schema.Types.ObjectId, ref: 'user'}
插入數據
var User = require('./model').User;
var Post = require('./model').Post;
var Comment = require('./model').Comment;
var tom = new User({name: 'Tom', age: 19});
var test = new Post({title: 'test', content: 'wakaka'});
var walala = new Comment({content: 'walala'});
tom
.save().then(function(user) {
test
.author = user;
walala
.author = user;
return Promise.all([test.save(), walala.save(), user]);
}).spread(function(post, comment, user) {
user
.posts.push(post);
user
.comments.push(comment);
post
.comments.push(comment);
return Promise.all([user.save(), post.save()]);
}).spread(function() {
console
.log('success');
}).catch(function(reason) {
console
.log(reason);
});
mongodb 查詢數據
> db.users.find().pretty()
{
"_id" : ObjectId("584a030733604a156a4f65ff"),
"name" : "Tom",
"age" : 19,
"comments" : [
ObjectId("584a030733604a156a4f6601")
],
"posts" : [
ObjectId("584a030733604a156a4f6600")
],
"__v" : 1
}
> db.posts.find().pretty()
{
"_id" : ObjectId("584a030733604a156a4f6600"),
"author" : ObjectId("584a030733604a156a4f65ff"),
"title" : "test",
"content" : "wakaka",
"comments" : [
ObjectId("584a030733604a156a4f6601")
],
"__v" : 1
}
> db.comments.find().pretty()
{
"_id" : ObjectId("584a030733604a156a4f6601"),
"author" : ObjectId("584a030733604a156a4f65ff"),
"content" : "walala",
"__v" : 0
}
populate
這裏經過傳入 Object 類型參數調用 populate。
Comment
.findOne({'content': 'walala'}).populate({path:'author', select: 'name'})
.exec().then(function(user) {
console
.log(user);
}).catch(function(reason) {
console
.log(reason);
});
{ _id: 584a030733604a156a4f6601,
author
: { _id: 584a030733604a156a4f65ff, name: 'Tom' },
content
: 'walala',
__v
: 0 }
假如,咱們要填充 Post 中的 author 和 comments,且填充 author 的 name 和 age,還有 comments 的 content; 不填充 author 和 comments 的 _id。
Post
.findOne({'title': 'test'}).populate('author comments', 'name age content -_id').exec()
.then(function(post) {
console
.log(post);
}).catch(function(reason) {
console
.log(reason);
});
Post
.findOne({'title': 'test'}).populate([{path: 'author', select: 'name age -_id'}, {path: 'comments', select: 'content -_id'}]).exec()
.then(function(post) {
console
.log(post);
}).catch(function(reason) {
console
.log(reason);
});
{ _id: 584a030733604a156a4f6600,
author
: { name: 'Tom', age: 19 },
title
: 'test',
content
: 'wakaka',
__v
: 1,
comments
: [ { content: 'walala' } ] }
有關populate的具體用法能夠參考mongoose的官方文檔http://mongoosejs.com/docs/populate.html#deep-populate
加入職業技能圈 q羣:272292492