联表(population)

原文:Population 翻译:小虾米(QQ:509129)

Population

在MongoDB没有join联表操作但有时我们还想引用其他集合中文档。这是population的出现的缘由。

Population是在文档中自动更换其他集合的文档指定路径的过程。我们可以填充一个单一的文档,多个文档,普通对象,多个简单的对象,或从查询返回的所有对象。让我们看看一些例子。

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值:

Population

到目前为止,我们还没有做任何不同的事情。我们只是创造了一个 Person 和一个 Story 。现在让我们使用查询生成器看一下填充story的_creator。

阵列的refs工作方式相同。在查询时调用populate方法和文档数组将在返回在原来的_ids的地方。

注:mongoose > = 3.6 在使用population暴露原始的_ids通过document#populated()方法。

设置Populated字段

在Mongoose > = 4,你也可以手动填充字段。

注意,这只工作在单个refs。你现在不能手动填充数组refs。

字段选择

如果我们只想要一些特定的字段返回填充的文档呢?这可以通过将常用的字段名语法作为填充方法的第二个参数来完成:

Populating multiple paths

如果我们想在同一时间填充多个路径呢?

在 mongoose > = 3.6,我们可以把一个空格分隔的路径名来填充字符串。3.6之前,您必须执行populate()方法多次。

查询条件和其他选项

如果我们想根据他们的年龄来填充我们的球迷数组,选择只是他们的名字,并返回最多,其中5个?

Refs to children

我们可能会发现,如果我们使用aaron对象,我们无法得到一个列表的stories。这是因为没有story的对象都“推”到aaron.stories

这里有两个观点。首先,很高兴aaron知道哪些stories是他的。

这使我们能够执行一个查找和填充组合:

这是值得商榷的,我们真的要两套指针作为他们可能不同步。相反,我们可以跳过,直接填充并find()我们感兴趣的故事。

更新refs

现在我们有一个故事,我们意识到_creator是错误的。我们可以通过更新refs通过Mongoose的铸件内部任何其他属性一样:

返回的文档查询population成为功能齐全,可保存文件,除非指定了精益选项。不与子文档混淆。请注意,当调用它的删除方法,因为你会从数据库中删除它,不仅仅是数组。

Populating 一个存在的文档

如果我们有一个现有的mongoose文档并且想要填充的一些它的路径。mongoose > = 3.6支持document#populate()方法。

Populating 多个存在的文档

如果我们有一个或多个mongoose文档,甚至是简单的对象(像mapReduce输出),我们可以让他们使用Model.populate() 方法 mongoose > = 3.6。这是为什么使用document#populate()query#populate()来populate文档。

Populating在多个层面

说你有一个用户模式,跟踪用户的朋友。

Populate可以让你得到一个用户的朋友的列表,但如果你也想要一个用户的朋友的朋友呢?指定populate选项告诉mongoose来populate所有用户的朋友的朋友的数组:

Populating整个数据库

让我们说,你有一个代表事件的模式,和一个代表对话的模式。每个事件都有一个相应的会话线程。

同时,假设事件和对话都存储在单独的MongoDB实例。

在这种情况下,您将无法正常populate()。conversation字段永远是空的,因为populate()不知道使用哪种模式。然而,您可以显式指定模型

这是一个被称为“跨数据库的populate“,因为它使你populate在MongoDB数据库和通过MongoDB实例。

动态参考

Mongoose也可以同是populate从多个集合。让我们说,你有一个用户模式,有一个“连接”的数组-用户可以连接到其他用户或组织。

以上的refpath属性意味着mongoose会看connections.kind路径确定模型用于populate()。换句话说,这refpath属性使您能够ref属性的动态。

Populate虚函数

新的4.5.0中

到目前为止,你只有稀少的基于_id字段。然而,这有时不是正确的选择。特别是,数组,无束缚成长是MongoDB的反模式。用mongoose鼬虚函数,您可以定义文档之间更复杂的关系。

下一步

现在我们已经掌握了population,让我来看一下连接

Last updated

Was this helpful?