我正在尝试返回创建文档的用户的名字和姓氏,以及最后修改它的用户。我populate()
以前在两个集合之间进行 JOIN,但它对我不起作用。
这是区域模型
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var model = new Schema({
NAME: { type: String, required: true, unique: true, max: 50, min: 3 },
STATUS: { type: String, default: 'active' },
ADDED_BY: { type: Schema.Types.ObjectId, ref: 'users' },
ADDED_DATE: { type: Date, default: Date.now },
MODIFY_BACKLOG :[{
USER: { type: Schema.Types.ObjectId, ref:'users' },
DATE: { type: Date, default: Date.now },
CURRENT: { type: String },
MODIFIED: { type: String }
}]
}, {collection :'areas'})
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('Area', model )
正如您所看到的索引ADDED_BY
,MODIFY_BACKLOG.USER
它们指的是集合users
。
这是用户模型
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var userSchema = new Schema({
PERSONAL_DATA: {
NAME: { type: String, required: [ true, 'The name is necessary' ], max: 50 },
LAST_NAME: { type: String, required: [ true, 'the lastname is necessary' ], max: 100 },
PHOTO: { type: String, max: 100 },
BIRTHDAY: { type: Date },
MARITIAL_STATUS: { type: Schema.Types.ObjectId, ref: 'maritial_statuses' },
GENDER: { type: String, max: 1 },
EMAIL: { type: String, required: true },
},
COMPANY_DATA: {
JOB: { type: Schema.Types.ObjectId, ref: 'jobs' },
AREA: { type: Schema.Types.ObjectId, ref: 'areas' },
ROLE: { type: Schema.Types.ObjectId, ref: 'roles' },
BOSS: { type: Schema.Types.ObjectId, ref: 'users' },
}
}, { collection: 'users' } )
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('User', userSchema )
由于该模型中的信息非常可靠,因此我决定将其分成PERSONAL_DATA, COMPANY_DATA
另外两个索引PAYMENT_DATA, ENGINE_DATA
,每个索引都保留引用父亲姓名的索引,但我不感兴趣,因为它们与问题,它是大约的模型。300 行。
里面COMPANY_DATA.AREA
是包含用户所属区域的地方,我认为与这个问题无关,但以防万一。
这是区域模型消耗的路径
var express = require('express'),
Areas = require('../../models/catalogs/areas'),
app = express()
app.get('/:from', (req, res) => {
var from = parseInt( req.params.from )
var populate = {
path: 'users',
select: 'NAME LAST_NAME'
}
Areas.find()
.sort('NAME').populate( populate )
.limit(10).skip(from)
.exec((error, data) => {
if (error) {
return res.status(500).json({
success: false,
error
})
}
Areas.count({}, ( err, total ) => {
res.status(200).json({
success: true,
data,
total
})
})
})
})
module.exports = app
对于该方法populate()
,我传递了一个具有相同名称的变量,我在其中引用集合以及我需要用户提供的数据。这就是我卡住的地方,因为它没有给我带来用户的信息,它只给我带来了该地区的信息,在这里我有三个问题
我怎样才能让收藏的加入尊重我?
我如何告诉它我需要的索引不是在文档的顶层,而是在 PERSONAL_DATA 中?我试过了
var populate = {
path: 'users',
select: 'PERSONAL_DATA.NAME PERSONAL_DATA.LAST_NAME'
}
但最后还是一样
区域模型中的索引MODIFY_BACKLOG
也有修改用户的ObjectId,怎么能说对用户的JOIN也是对那个索引做的呢?
我留下一个答案的例子
{
"success": true,
"data": [{
"STATUS": "active",
"_id": "5c547f4adadf433914f72c8c",
"NAME": "Contabilidad y Finanzas",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-01T17:18:02.680Z",
"__v": 0,
"MODIFY_BACKLOG": []
}, {
"STATUS": "active",
"_id": "5c645f476491cf093c51c38e",
"NAME": "Recursos Humanos",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-13T18:17:43.036Z",
"__v": 0,
"MODIFY_BACKLOG": [{
"DATE": "2019-02-13T19:43:18.273Z",
"_id": "5c6473561370462754939107",
"USER": "5c4f562deec6f4defeea759b",
"CURRENT": "active",
"MODIFIED": "{\"STATUS\":\"inactive\"}"
}, {
"DATE": "2019-02-13T19:43:24.213Z",
"_id": "5c64735c1370462754939108",
"USER": "5c4f562deec6f4defeea759b",
"CURRENT": "inactive",
"MODIFIED": "{\"STATUS\":\"active\"}"
}]
}],
"total": 5
}
你有一些错误,我会一点一点地详细说明
问题
您想使用 Mongoose 作为 ODM 从 Express 应用程序查询 Mongo 数据库。
正在查阅的文档属于集合
areas
,并且有一个引用ObjectId
另一个文档的字段。即,该字段ADDED_BY
包含_id
对集合中文档字段的引用users
。执行的查询使用
populate()
(Mongoose) 方法告诉 Mongo 引擎您要返回users
包含引用的字段中的字段集(来自集合文档)。使用命名对象
populate
作为参数传递给方法。populate()
解决方案
在这里,我将指出您所犯的错误以及一些建议:
我在您的代码中看到的第一个错误是在模型定义中
User
:这一行应该是:
我猜这是“复制和粘贴”错误
那么我可以给你的一个建议是你如何定义你的参考:
我通常使用一个单数名称,它也与我所指的模型匹配,而不是集合的名称。正如我所说,这只是一个建议:
最后,您使用该方法的方式
populate()
是导致您的问题的原因。在Mongoose 官方文档中,它声明如下:(自己的翻译)
鉴于此,问题在于您没有指定要正确替换数据的路径。在我看来,您错误地假设它
ref
是要在要替换的路径中使用的名称。所以你的对象
populate
应该是这样的:你可以看到我使用的
PERSONAL_DATA.NAME
和PERSONAL_DATA.LAST_NAME
作为参数的select
.至于
array
存储修改日志的那个。解决方案是相同的,但略有不同。让我们创建一个对象,命名populateLog
如下:如您所见,
path
对象的字段是,而MODIFY_BACKLOG.USER
正是我们要填充附加数据的字段。USER
MODIFY_BACKLOG
array
Mongoose 将用我们请求的数据填充 的每个元素。现在我们可以调用方法链中的方法:
如您所见,我调用了该方法两次
populate()
并将相应的对象传递给每个对象。进行这些小的更改,您的代码应该可以工作。
使用 Postman 对我自己的实现的响应示例
GET
如下:如您所见,返回的文档包含我们使用方法填充的信息
populate()
,包括 fieldADDED_BY
和 fieldMODIFY_BACKLOG
,因为后者是 aarray
,所以每个元素都array
包含正确的信息。我希望这可以帮助您解决问题。