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 数组的主要内容,如果未能解决你的问题,请参考以下文章

Mongo - 通过_id更新嵌套的对象数组

如何更新nodejs中的mongo嵌套数组?

Mongoose 在多个数组中填充嵌套元素

试图在 mongoose 中填充一个嵌套数组,抛出一个看似无关的 CastError,我不明白为啥

在 mongoose 中填充嵌套数组 - Node.js

$lookup 嵌套对象数组