Mongoose:填充嵌套的 id 数组
Posted
技术标签:
【中文标题】Mongoose:填充嵌套的 id 数组【英文标题】:Mongoose: Populating a nested array of ids 【发布时间】:2019-12-06 22:24:24 【问题描述】:我一直在网上寻找解决方案,但似乎找不到我的问题的答案。 Here's a very similar case, 但由于某种原因,我的文档仍然没有被填充。 以下是架构:
客户架构:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var customerSchema = new Schema(
_id: type: Schema.Types.ObjectId,
auditTrail: type: Object,
thirdParty: [type: Schema.Types.ObjectId, ref: 'Thirdparty'],
docRefs: type: Object,
salesRep: type: Array,
commentsArr: type: Array
);
module.exports = mongoose.model('Customer', customerSchema);
第三方的:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var thirdPartySchema = new Schema(
_id: type: Schema.Types.ObjectId,
type: type: String,
name: type: String,
vat: type: String,
corpoPhone: type: String,
corpoMail: type: String,
corpoWeb: type: String,
activityNumber: type: String,
addresses: type: Array,
contacts: [type: Schema.Types.ObjectId, ref: 'Contact'], // <-- ARRAY OF ObjectIds /!\
);
module.exports = mongoose.model('Thirdparty', thirdPartySchema);
和联系人的:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var contactSchema = new Schema(
_id: type: Schema.Types.ObjectId,
title: type: String,
role: type: String,
firstName: type: String,
lastName: type: String,
phone: type: String,
mobile: type: String,
email: type: String
);
module.exports = mongoose.model('Contact', contactSchema);
这是我的电话:
Customer
.find()
.populate(
path: 'thirdParty',
populate: path: 'contacts', model: 'Contact'
)
.then(
//... Do something
)
如果第三方在客户中完全填充,则联系人绝对不会... 这是“响应”的日志:
我做错了什么?
提前致谢!
【问题讨论】:
【参考方案1】:Array 内的Array 不能直接工作。您需要$unwind
进行进一步操作和两个级别的$group
。
冗长,但这是您实现要求的方式。
db.getCollection('Customer').aggregate([
$unwind: "$thirdParty",
$lookup: from: 'Thirdparty', localField: 'thirdParty', foreignField: '_id', as: 'thirdParty',
$unwind: "$thirdParty",
$unwind: "$thirdParty.contacts",
$lookup: from: 'Contact', localField: 'thirdParty.contacts', foreignField: '_id', as: 'thirdParty.contacts',
$unwind: "$thirdParty.contacts",
$group:
_id:
custid: "$_id",
tId: "$thirdParty._id"
,
auditTrail: $first: "$auditTrail",
docRefs: $first: "$docRefs",
salesRep: $first: "$salesRep",
commentsArr: $first: "$commentsArr",
contactsArr: $push: "$thirdParty.contacts",
thirdParty: $first:"$thirdParty"
,
$group:
_id: "$_id.custid",
auditTrail: $first: "$auditTrail",
docRefs: $first: "$docRefs",
salesRep: $first: "$salesRep",
commentsArr: $first: "$commentsArr",
thirdParty: $push:
"_id": "$thirdParty._id",
"type" : "$thirdParty.type",
"name" : "$thirdParty.name",
"vat" : "$thirdParty.vat",
"corpoPhone" : "$thirdParty.corpoPhone",
"corpoMail" : "$thirdParty.corpoMail",
"corpoWeb" : "$thirdParty.corpoWeb",
"activityNumber" :"$thirdParty.activityNumber",
"addresses" : "$thirdPartyaddresses",
"contacts": "$contactsArr"
,
])
下面是输出:
"_id" : ObjectId("5d3f0a70d4a630e6a5499d3a"),
"auditTrail" : ,
"docRefs" : ,
"salesRep" : [],
"commentsArr" : [],
"thirdParty" : [
"_id" : ObjectId("5d3fe4ddd4a630e6a5499d3b"),
"type" : "type2",
"name" : "type2",
"vat" : "type2",
"corpoPhone" : "type2",
"corpoMail" : "type2",
"corpoWeb" : "type2",
"activityNumber" : "type2",
"contacts" : [
"_id" : ObjectId("5d3f09edd4a630e6a5499d38"),
"title" : "title1",
"role" : "role1",
"firstName" : "firstname1",
"lastName" : "lastname1",
"phone" : "phone1",
"mobile" : "mobile1",
"email" : "email1"
,
"_id" : ObjectId("5d3fe547d4a630e6a5499d3d"),
"title" : "title2",
"role" : "role2",
"firstName" : "firstname2",
"lastName" : "lastname2",
"phone" : "phone2",
"mobile" : "mobile2",
"email" : "email2"
]
,
"_id" : ObjectId("5d3f0a36d4a630e6a5499d39"),
"type" : "type1",
"name" : "type1",
"vat" : "type1",
"corpoPhone" : "type1",
"corpoMail" : "type1",
"corpoWeb" : "type1",
"activityNumber" : "type1",
"contacts" : [
"_id" : ObjectId("5d3f09edd4a630e6a5499d38"),
"title" : "title1",
"role" : "role1",
"firstName" : "firstname1",
"lastName" : "lastname1",
"phone" : "phone1",
"mobile" : "mobile1",
"email" : "email1"
]
]
【讨论】:
嘿哈迪克,感谢您的回答。但是,虽然 Mongoose 中有一个聚合函数,但我觉得您使用的语法是直接来自 MongoDB 的 API 而不是 Mongoose,对吗? 对,你可以在使用mongoose聚合函数获取记录的同时使用这个聚合。 好吧...让我试试。正如你所说,这似乎有点“冗长”,猫鼬的文件似乎暗示有解决方案mongoosejs.com/docs/populate.html#deep-populate... 您的解决方案没有错误,但我得到一个完全空的文档数组: "message": "Customer successfully fetched", "customers": [ ]
猫鼬搞定了!我将发布解决方案。不管怎么说,多谢拉! :)【参考方案2】:
知道了!我错过了模型中的导入语句:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Contact = require('./contact'); // <--- THIS LINE RIGHT HERE
var thirdPartySchema = new Schema(
_id: type: Schema.Types.ObjectId,
type: type: String,
name: type: String,
vat: type: String,
corpoPhone: type: String,
corpoMail: type: String,
corpoWeb: type: String,
activityNumber: type: String,
addresses: type: Array,
contacts: [type: Schema.Types.ObjectId, ref: 'Contact'],
);
module.exports = mongoose.model('Thirdparty', thirdPartySchema);
请求看起来像:
Customer
.find()
.populate(
path: 'thirdParty',
populate: path: 'contacts', model: 'Contact'
)
.then(
documents =>
res.status(200).json(
message: 'Customer successfully fetched',
customers: documents
);
).catch(err => res.status(404).json(message: 'No customer found!', error: err));
);
现在我的“对象”得到了正确填充:
"message": "Customer successfully fetched",
"customers": [
"thirdParty": [
"addresses": [
"street": "AVENIDA ESTADOS UNIDOS, 141",
"streetcomp": "",
"streetcomp2": "",
"city": "SAN BARTOLOME DE TIRAJANA ",
"cp": "35290",
"state": "PALMAS (LAS)",
"country": "spain",
"main": true
,
"street": "OTRA DIRECCION DUMMY",
"streetcomp": "",
"streetcomp2": "",
"city": "MADRID",
"state": "MADRID",
"country": "spain",
"main": false
],
"contacts": [
"_id": "5cf0f6f2a3e9cf847c5861af",
"title": "Mrs.",
"role": "CFO",
"firstName": "John",
"lastName": "Doe",
"phone": "912345654",
"mobile": "673369900",
"thirdParty_id": "5cf0f6d0a3e9cf847c5861aa",
"addresses": [
"street": "AVENIDA ESTADOS UNIDOS , 141",
"streetcomp1": "TUNTE",
"streetcomp2": "",
"cp": "35290",
"city": "SAN BARTOLOME DE TIRAJANA ",
"state": "PALMAS (LAS)"
],
"email": "jdoe@ketchup.com",
"auditTrail":
"creation":
"user_id": "1",
"creationDate": "1559213796974"
,
"modification": [
"user_id": "1",
"modifDate": "1559213833358"
]
],
"_id": "5cf0f6d0a3e9cf847c5861aa",
"type": "customer",
"name": "ketchup",
"vat": "B87451084",
"corpoPhone": "918388544",
"corpoMail": "obras@ferrometal.net",
"corpoWeb": "http://ferrometalcimentaciones.es/",
"activityNumber": "5630"
],
"salesRep": [
"user_id": "USER_ID to be defined",
"dateBegin": "1559212324146",
"active": true
,
"user_id": "USER_ID to be defined",
"dateBegin": "1559212324146",
"active": false
],
"commentsArr": [
"user_id": "USER_ID to be changed to name",
"comment": "this is a great customer!"
,
"user_id": "USER_ID to be changed to name",
"comment": "This is a test"
],
"_id": "5cf0f704a3e9cf847c5861b2",
"auditTrail":
"modifications": [
"modificationDate": "1559211664284",
"user_id": "A123"
],
"creation":
"creationDate": "1559211664284",
"user_id": "A123"
,
"docRefs":
"fs": [
"name": "mod 200 2018",
"comment": "should be approved",
"url": "www.google.com",
"uploadDate": "1559212324146",
"originalName": "mod200-2018.pdf",
"mime": "pdf",
"type": "fs",
"typeName": "Financial Statements"
],
"id": [
"name": "Jose-Pedro",
"comment": "ID Valido",
"url": "/somehwere/else",
"uploadDate": "1559212324146",
"originalName": "id-jp.pdf",
"mime": "pdf",
"type": "id",
"typeName": "Identification Document"
],
"ad": [
],
"cd": [
],
"pd": [
],
"od": [
]
,
"active": true
,
"thirdParty": [
"addresses": [
"street": "CALLE MORGAN , 2 - BJ 2 B",
"streetcomp": "",
"streetcomp2": "",
"city": "BILBAO",
"cp": "48014",
"state": "BIZKAIA",
"country": "spain",
"main": true
],
"contacts": [
"_id": "5cf0f6f2a3e9cf847c5861af",
"title": "Mrs.",
"role": "CFO",
"firstName": "John",
"lastName": "Doe",
"phone": "912345654",
"mobile": "673369900",
"thirdParty_id": "5cf0f6d0a3e9cf847c5861aa",
"addresses": [
"street": "AVENIDA ESTADOS UNIDOS , 141",
"streetcomp1": "TUNTE",
"streetcomp2": "",
"cp": "35290",
"city": "SAN BARTOLOME DE TIRAJANA ",
"state": "PALMAS (LAS)"
],
"email": "jdoe@ketchup.com",
"auditTrail":
"creation":
"user_id": "1",
"creationDate": "1559213796974"
,
"modification": [
"user_id": "1",
"modifDate": "1559213833358"
]
],
"_id": "5cf629538c2d290f39a9b18b",
"type": "customer",
"name": "ginegorama",
"vat": "B95551776",
"activityNumber": "8690"
],
"salesRep": [
"user_id": "1",
"dateBegin": "1559212324146",
"active": true
,
"user_id": "2",
"dateBegin": "1559212324146",
"active": false
],
"commentsArr": [
"user_id": "USER_ID to be changed to name",
"comment": "this is a great customer!"
],
"_id": "5cf6296a8c2d290f39a9b18c",
"auditTrail":
"modifications": [
"modificationDate": "1559211664284",
"user_id": "1"
],
"creation":
"creationDate": "1559211664284",
"user_id": "1"
,
"docRefs":
"fs": [
"name": "mod 200 2018",
"comment": "should be approved",
"url": "/somewhere",
"uploadDate": "1559212324146",
"originalName": "mod200-2018.pdf",
"mime": "pdf",
"type": "fs",
"typeName": "Financial Statements"
],
"id": [
],
"ad": [
],
"cd": [
],
"pd": [
],
"od": [
]
,
"active": false
]
【讨论】:
以上是关于Mongoose:填充嵌套的 id 数组的主要内容,如果未能解决你的问题,请参考以下文章