1

I have 6 Different Collections in my mongodb, the 5 collections are to connected to one connection, But I didn't used ref, instead I made is that I get the Id of 5 collections and then saved it to the 6th collection namely "List" so that I still have common field that I can use as a reference

Here is my Collections structure

list Collection
   var ListDoc = new mongoose.Schema({
       type_id        : {type: Schema.Types.ObjectId, required: true},
       detail_id      : {type: Schema.Types.ObjectId, required: true},
       address_id     : {type: Schema.Types.ObjectId, required: true},
       inquiries_id   : {type: Schema.Types.ObjectId, required: true},
       account_id     : {type: Schema.Types.ObjectId, required: true}
    });
    module.exports = mongoose.model('List', ListDoc);

Account Collection
    var accountDoc = new mongoose.Schema({
        email     : {type: String, unique: true, required: true},
        password  : {type: String, required: true}
    });
    module.exports = mongoose.model('Accounts', accountDoc );

Type Collection
    var TypeDoc = new mongoose.Schema({
        type   : {type: String, required: true},
        class  : {type: String, required: true},
    });
    module.exports = mongoose.model('Type', TypeDoc);

Detail Collection
    var DetailDoc = new mongoose.Schema({
        bedr         : {type: Number, required: true},
        diningr      : {type: Number, required: true},
        livingr      : {type: Number, required: true},
        kitchenr     : {type: Number, required: true}
        bathr        : {type: Number, required: true}
    });
    module.exports = mongoose.model('Detail', DetailDoc);

Address Collection
    var AddressDoc = new mongoose.Schema({
        city     : {type: String, required: true},
        brgy     : {type: String, required: true},
        street   : {type: String, required: true},
        bldgno   : {type: String, required: true},
        floorno  : {type: String, required: true},
        roomno   : {type: String, required: true}
    });
    module.exports = mongoose.model('Address', AddressDoc);

 Inquiries Collection
    var InquiriesDoc = new mongoose.Schema({
        inquiries    : {type: Number, required: true},
        views        : {type: Number, required: true},
    });
    module.exports = mongoose.model('Inquiries', InquiriesDoc);

Note: each collection has different .js file

The list Collection will have the Ids of 4 another Collection.

This is what Im trying to achieve

[ {
   "_id": "5907747e424c860f7495ad46",
   "account_id": "5908f3381cd9810ea8e2b517",
   "type": {
       "type" : "apartment",
       "class" : "middle"
      },
   "detail": {
       "bedr": 4,
       "diningr": 2,
       "livingr": 1,
       "kitchenr": 1,
       "bathr": 4
    },
   "address": {
       "city" : "lucena",
       "brgy" : "8",
       "street" : "rose",
       "bldgno" : "24",
       "floorno": "2",
       "roomno": "205"  
     },
  "inquiries": {
       "views" : 0,
       "inquires" : 0
      }
  },
  {
   "_id": "5907747e424c860f7495ad47",
   "account_id": "5908f3381cd9810ea8e2b517",
   "type_id": {
       "type" : "apartment",
       "class" : "middle"
             },
   "detail": {
       "bedr": 4,
       "diningr": 2,
       "livingr": 1,
       "kitchenr": 1,
       "bathr": 4
    },
   "address": {
       "city" : "lucena",
       "brgy" : "8",
       "street" : "rose",
       "bldgno" : "24",
       "floorno": "3",
       "roomno": "307"  
     },
   "inquiries": {
       "views" : 0,
       "inquires" : 0
       }
   }, ]

First I get all the data inside the list collection which is the Ids of 4 Collection and then I tried to loop it so that I can get the another data from other collections

for(var loop =0 ; loop < list.length; loop++){
        var pt_id = list[loop].type_id;
        var pa_id = list[loop].address_id;
        var pd_id = list[loop].detail_id;
        var pi_id = list[loop].inquiries_id;
 }

I'd use async inside for loop then concate it into "testresult" var using +=

here is my code

var PL = require('../models/list');
var PT = require('../models/type');
var PA = require('../models/address');
var PD = require('../models/detail');
var PI = require('../models/inquiry');
var cryption    = require('../services/encrypt_decrypt');
var crypt = new cryption();
var async = require('async');


module.exports.read = function (request, response) {
var decryptedId = crypt.decrypt(request.decode.id);


var propertylistquery = PL.find({}).where('account_id').equals(decryptedId).select({"_id":0,"__v":0});

propertylistquery.exec(function (error, list) {
    if (error) {
        return response.status(500).send({success: false, error: error, message: 'Something went wrong.'});
    }
    if (!list) {
        return response.status(200).send({success: false, message: 'User not found in the database.'});
    }

    var testresult;
    for(var loop =0 ; loop < list.length; loop++){
        var pt_id = list[loop].type_id;
        var pa_id = list[loop].address_id;
        var pd_id = list[loop].detail_id;
        var pi_id = list[loop].inquiries_id;

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Getting the property type
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        var ptquery = PT.find({}).where('_id').equals(pt_id).select({"__v":0});

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Getting the property address
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        var paquery = PA.find({}).where('_id').equals(pa_id).select({"__v":0});

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Getting the property detail
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        var pdquery = PD.find({}).where('_id').equals(pd_id).select({"__v":0});

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Getting the propertyinquiry
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        var piquery = PI.find({}).where('_id').equals(pi_id).select({"__v":0});

        var resources = {
            Type        :   ptquery.exec.bind(ptquery),
            Address     :   paquery.exec.bind(paquery),
            Detail      :   pdquery.exec.bind(pdquery),
            Inquiry     :   piquery.exec.bind(piquery)
        };

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Asynchrozing the queries
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        async.parallel(resources, function (error, results){
            if (error) {
                response.status(500).send(error);
                return;
            }

            testresult += results;
            //console.log(results);
        });
    }


    console.log(testresult);
    response.json({success: true, data: list, message: 'Successfully fetched all property.'});
});

};

when I log the "result" var inside for loop, it has a data but when I try to log the "testresult" var, it is undefined

What will I do get my desire output?

0

1 Answer 1

1

Just use the $lookup operator to do the joins from the other collections where you can specify the collection in the same database to perform the join with and the results stored in an array field added to the input documents.

The following example demonstrates the operation with $lookup. To get the desired output you would then need to apply the $arrayElemAt operator on the resulting arrays, this will return the subdocument in the array specified by an index, 0 in this case as it's the only element in the array (result of a one-to-one relationship will give a single element array with $lookup):

var PL = require('../models/list');
var cryption    = require('../services/encrypt_decrypt');
var crypt = new cryption();

module.exports.read = function (request, response) {
    var decryptedId = crypt.decrypt(request.decode.id);

    PL.aggregate([
        { "$match": { "account_id": mongoose.Types.ObjectId(decryptedId) } },
        {
            "$lookup": {
                "from": "pt", /* make sure the underlying collection name is correct */
                "localField": "type_id",
                "foreignField": "_id",
                "as": "types"
            }
        },
        {
            "$lookup": {
                "from": "pa", /* make sure the underlying collection name is correct */
                "localField": "address_id",
                "foreignField": "_id",
                "as": "addresses"
            }
        },
        {
            "$lookup": {
                "from": "pd", /* make sure the underlying collection name is correct */
                "localField": "detail_id",
                "foreignField": "_id",
                "as": "details"
            }
        },
        {
            "$lookup": {
                "from": "pi", /* make sure the underlying collection name is correct */
                "localField": "inquiries_id",
                "foreignField": "_id",
                "as": "inquiries"
            }
        },
        {
            "$project": {
                "account_id": 1,
                "type": { "$arrayElemAt": ["$types", 0] },
                "detail": { "$arrayElemAt": ["$addresses", 0] },
                "address": { "$arrayElemAt": ["$details", 0] },
                "inquiries": { "$arrayElemAt": ["$inquiries", 0] },
            }           
        }
    ]).exec(function (error, results){
        if (error) {
            response.status(500).send(error);           
        }

        console.log(results);
        response.json({
            success: true, 
            data: results, 
            message: 'Successfully fetched all property.'
        });
    });
};
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your help, but when I try your code, it gives an empty array, then when I remove the mongoose.Types.ObjectId() in $match because account_id is a string field, it gives the id and account_id of the list collection only. then I try to add the mongoose.Types.ObjectId() in the foreign field because the "_Id" is object, it gives this error "Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"
You can't add mongoose.Types.ObjectId() to the localField and foreignFields options in $lookup. Can you update your question to show the actual schema definitions code for all the models in question?
Thank you sir chridam, I update my questions, I include my schema for every collection
Thank you sir chridam, after a couple of hour of debugging it, finally I solved it. I still used your answer above, the problem is not the type of the field but the name of the collections it self. the name of collection I made is different in the name of collection stored in database, like this. Model or the one I made: ("Address") in Mongodb ("addresses")
Glad you managed to crack the issue, I put in some comments /* make sure the underlying collection name is correct */ which I think you missed at the very beginning but now that you've got around getting that correct, kudos to you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.