Mongoose使用population建立关系链接实例说明

引用文档:

基于Node.js项目实践,构建可扩展的web应用(当当书籍地址)

Mongoose 使用之 Population

Mongoose API v4.4.13 .
版本信息:"express": "~4.13.1","mongoose":"4.3.6"

MongoDB、Mongoose

MongoDB是NoSQL数据库,易扩展,比传统数据库更适合处理大数据。Mongoose是基于Node.js、MongoDB的高级ORM类库。链接数据库简单,不必每次开启关闭数据库。对于NoSql数据库来说,数据库中是不存储关系数据的,并没有主键、外键约束之分,但是我们可以在应用层进行存储,Mongoose提供的这一特性,名为population,允许我们使用不同集合来填充文档特定部分,个人理解感觉就像是通过外键可以获得外键所在表中的信息这样的查询效果。

在介绍population之前,先简单介绍一下Mongoose的一些名词:

Schema:一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。

Model:由Schema发布生成的模型,具有抽象性和行为的数据库操作对。

实例说明:

首先引入mongoose模块,连接数据库

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');

链接数据库之后要定义原型,原型是一个json格式的类,Mongoose的原型支持下面这些数据类型:

  • String
  • Number
  • Boolean
  • Buffer:node.js二进制类型,多用于图像、PDF、档案等;
  • Date:ISO标准格式化日期类型;
  • Array
  • Schema.Types.ObjectId:MongoDB中的一个典型24个字符,12字节的十六进制数字字符串;
  • Schema.Type.Mixed:任何类型数据。

建立的实例场景为一个聊天室中可以有多名用户。

建立用户原型:

var UserSchema = Schema({
  _id:Number,
  name : String,
  sex:String
})
var User = mongoose.model('users', UserSchema);//将原型和方法编译为一个模块,users也将是存入数据库中的集合的名称。

建立聊天室原型:

var RoomSchema = Schema({
  roomNumber:String,
  roomMember:[{
    type:Number, ref: 'users'
  }],
})
var Room = mongoose.model('rooms',RoomSchema);//将原型和方法编译为一个模块

创建实例:

var lily = new User({'_id':1000,'name': 'lily','sex':'F'});
var lucy = new User({'_id':1001,'name':'lucy','sex':'F'});
var room = new Room({
  'roomNumber':'1',
  'roomMember':[lily._id,lucy._id]//此处所调用的必须为_id字段,如果创建原型时未创建id字段,则数据库会自动生成Schema.Types.ObjectId类型的_id
});

将数据存入数据库:

function callback(err,doc){
  if(err) throw err;
  console.log(doc);//返回的是存入数据库中的记录
};
lily.save(callback);
lucy.save(callback);
room.save(callback);

数据库中查询记录

Mongoose使用population建立关系链接实例说明_第1张图片
数据库中的查询记录

population的使用
在查找数据的而过程中使用population可以输出相应的实例记录

Room.findOne({roomNumber:'1'})
.populate('roomMember')
.exec(callback);

通过population查询之后,在控制台中打印的console.log(doc)如下图所示:

Mongoose使用population建立关系链接实例说明_第2张图片

通过图片我们可以看到在room原型中所ref的user原型中符合的信息已经全部都输出了,这样就不用多集合查询获得信息了,虽然各集合之间都没有关系,但是我们通过使用population在应用层存储它们,太感人了!
Demo地址: https://github.com/a67c/populateDemo

出现的错误提示及原因

 E11000 duplicate key error index: populateDemo.users.$_id_ dup key: { : 1000 }

出现了重复的键,由于用户的_id是手动插入的,而非系统自动生成的ObjectedId(),所以如果再插入_id:1000,就会报此类错误。

Cast to ObjectId failed for value "XXX" at path "_id".

调用的参考值不是_id,按照例子来说就是在实例化时'roomMember':[lily._id,lucy._id]调用一定要是_id字段!
小扩展

1、当我不需要获得一条记录的全部信息时可以在populate中对于输出的信息做限制

Room.findOne({roomNumber: '1'})
.populate('roomMember','name')
.exec(callback);

在populate中添加User中的字段name,那么在输出的过程中就会只显示name和_id字段。

ps:错误之处还请指出,多多指教

个人博客:
进击的程序茗

你可能感兴趣的:(Mongoose使用population建立关系链接实例说明)