[NodeJS] Mongoose Populate 基本使用

转载自 https://blog.csdn.net/elliott_yoho/article/details/53537147

在使用 mongoose 时,想通过一个外键与另一张表建立关联时,不知该如何简单快捷的实现,特地去查了一下,发现了 population 这个功能,在此简单记录下 mongoose 的 populate 使用。

环境
Node: v7.0.0
Bluebird: v3.4.6
Mongoose: v4.6.8
参考文档
ECMAScript 6 入门 —— Promise对象, 阮一峰
Mongoose 之 Population 使用, aikin
Mongoose API v4.7.2

使用方法
我觉得参考文档里的那篇文章 Mongoose 之 Population 使用, aikin 写的很详细了,这里为方便看,我把它复制过来了,所以,使用方法部分基本出自上述文章.

语法
Query.populate(path, [select], [model], [match], [options])
1
参数 Option
path
类型:String或Object。

String类型的时, 指定要填充的关联字段,要填充多个关联字段可以以空格分隔。
Object类型的时,就是把 populate 的参数封装到一个对象里。当然也可以是个数组。下面的例子中将会实现。
select
类型:Object或String,可选,指定填充 document 中的哪些字段。

Object类型的时,格式如: {name: 1, _id: 0},为0表示不填充,为1时表示填充。
String类型的时,格式如: “name -_id”,用空格分隔字段,在字段名前加上-表示不填充。详细语法介绍 query-select
尝试中发现 select 默认会填充 _id。

model
类型:Model,可选,指定关联字段的 model,如果没有指定就会使用Schema的ref。

match
类型:Object,可选,指定附加的查询条件。

options
类型:Object,可选,指定附加的其他查询选项,如排序以及条数限制等等。

基本使用
数据模型
创建三个Schema和Model。

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'}

// 这里的 ref: ‘user’ 是第一行的 mongoose.model(‘user’, userSchema) 第一个参数。
插入数据

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
填充单个字段
假如,填充 Comment 中的 author。

代码
这里通过传入 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。

代码
以下两种写法效果是一样的。

// 若是用字符串填写,select 同时作用于两个字段,即 author 和 comments 都会填充 name age content,若该字段没有这些数据,则不填充。
Post.findOne({'title': 'test'}).populate('author comments', 'name age content -_id').exec()
.then(function(post) {
  console.log(post);
}).catch(function(reason) {
  console.log(reason);
});
 
// 数组形式可以单独对某一字段用 select 选择要填充的数据。
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' } ] }

猜你喜欢

转载自blog.csdn.net/qq_34629352/article/details/85219446