JerVi
JerVi

Reputation: 131

How to get data from collection in node js using mongoose

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?

Upvotes: 1

Views: 766

Answers (1)

chridam
chridam

Reputation: 103475

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.'
        });
    });
};

Upvotes: 1

Related Questions