How to populate the model of populated model in mongoose - node.js

I come from the MySQL background. I am new to MongoDB. How can I get the details model of a populated model? Please help me
Listing Model
var listing = new mongoose.Schema({
ru_id : [{type: mongoose.Schema.Types.ObjectId, ref: 'Rentable_unit' }],
pro_id : [{type: mongoose.Schema.Types.ObjectId, ref: 'Property' }]
})
Property Model
var property = new mongoose.Schema({
address_id : [{type: mongoose.Schema.Types.ObjectId, ref: 'Address' }],
pro_authority : [{type : mongoose.Schema.Types.ObjectId, ref: 'User' }]
})
Address Model
var address = new mongoose.Schema({
address_line_1: { type: String },
address_line_2: { type: String }
})
I need to get the data from listing address based on property how can I do this.

You will have to load your listing, then your property and then the address with three queries. It's referenced in the article below as application-level join.
If you need to do this a lot you should consider changing your schema design. You could check this blog post from mongodb for possible solutions.

Related

Check against multiple fields when using Mongoose Virtual schema?

I am a little stuck with trying to figure out the best way to populate a virtual schema in my db. In this instance, I want to check against multiple fields but I do not know any way to do this or alternative ways.
I had hoped I could just use some string arrays in the 'localField' & 'foreignField' keys of the virtual schema but this was not the case.
The user has a 'Series' _id saved, and the virtual schema 'leagues' gets all leagues that the user is entered into too, the catch is a league belongs to different Series. I want to only retrieve the leagues that the user is entered into & that match up with the user's series _id also...
As you can see currently this virtual schema just returns all the leagues the user is entered into regardless of the series. :(
Any ideas? I have been very confused about how to achieve this.
const schema: mongoose.Schema = new mongoose.Schema({
_id: {
type: mongoose.Schema.Types.ObjectId,
auto: true
},
username: {
type: String,
unique: true,
},
series: {
ref: 'Serie',
type: mongoose.Schema.Types.ObjectId,
autopopulate: {
maxDepth: 1,
select: ['title']
}
}
});
schema.virtual('leagues', {
ref: 'League',
localField: '_id',
foreignField: 'users',
autopopulate: {
maxDepth: 1,
select: ['title', 'engineSize', 'host', 'series']
}
});
The league schema looks like this
const schema: mongoose.Schema = new mongoose.Schema({
_id: {
type: mongoose.Schema.Types.ObjectId,
auto: true
},
title: String,
series: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Serie',
},
users: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
}]
});
This was my solution to checking against multiple fields in mongoose using a getter.
schema.virtual('motoduel').get(function () {
return motoduelModel.findOne({
event: this.series.upcomingEvent._id,
riderGroup: this.riderGroup._id
});
});

Mongoose - store multiple model types in one field

I have a schema which looks like this:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const timestamps = require('mongoose-timestamps');
const BidSchema = new Schema({
bidder: {
type: Schema.ObjectId,
ref: 'Buyer'
},
counterOffer: {
type: Schema.ObjectId,
ref: 'Counter_Offer'
},
box: {
type: Schema.ObjectId,
ref: 'Box'
},
status: {
type: String,
enum: ['Pending', 'Approved', 'Disapproved']
},
bidPrice: Number,
bidTimeout: {
type: Date,
default: Date.now
},
isAnonymous: Boolean,
});
BidSchema.plugin(timestamps);
module.exports = mongoose.model('Bid', BidSchema);
I want to store multiple data types in the Box field. For example, I have a Box model and also I have a GroupedBox model. I want to be able to store id for both of these schemas and to be able to populate this field accordingly. For instance, if the document will store an ObjectId that references a GroupedBox document, the populate method will fetch the right GroupedBox document. Same goes for a Box document id.
I read about Mixed field types but I don't see how that can help me.
replace box field in your code with this:
box: {
box: { type: Schema.Types.ObjectId, ref: 'Box' },
groupedBox : { type: Schema.Types.ObjectId, ref: 'GroupedBox' }
}
To populate box you need to access box with a dot populate("box.box") similar to groupedBox you populate it this way populate("box.groupedBox")

Mongoose populate ObjectID from multiple possible collections

I have a mongoose model that looks something like this
var LogSchema = new Schema({
item: {
type: ObjectId,
ref: 'article',
index:true,
},
});
But 'item' could be referenced from multiple collections. Is it possible to do something like this?
var LogSchema = new Schema({
item: {
type: ObjectId,
ref: ['article','image'],
index:true,
},
});
The idea being that 'item' could be a document from the 'article' collection OR the 'image' collection.
Is this possible or do i need to manually populate?
Question is old, but maybe someone else still looks for similar issues :)
I found in Mongoose Github issues this:
mongoose 4.x supports using refPath instead of ref:
var schema = new Schema({
name:String,
others: [{ value: {type:mongoose.Types.ObjectId, refPath: 'others.kind' } }, kind: String }]
})
In #CadeEmbery case it would be:
var logSchema = new Schema({
item: {type: mongoose.Types.ObjectId, refPath: 'kind' } },
kind: String
})
But I did't try it yet...
First of all some basics
The ref option says mongoose which collection to get data for when you use populate().
The ref option is not mandatory, when you do not set it up, populate() require you to give dynamically a ref to him using the model option.
#example
populate({ path: 'conversation', model: Conversation }).
Here you say to mongoose that the collection behind the ObjectId is Conversation.
It is not possible to gives populate or Schema an array of refs.
Some others Stackoverflow people asked about it.
Soluce 1: Populate both (Manual)
Try to populate one, if you have no data, populate the second.
Soluce 2: Change your schema
Create two link, and set one of them.
var LogSchema = new Schema({
itemLink1: {
type: ObjectId,
ref: 'image',
index: true,
},
itemLink2: {
type: ObjectId,
ref: 'article',
index: true,
},
});
LogSchema.find({})
.populate('itemLink1')
.populate('itemLink2')
.exec()
Dynamic References via refPath
Mongoose can also populate from multiple collections based on the value of a property in the document. Let's say you're building a schema for storing comments. A user may comment on either a blog post or a product.
body: { type: String, required: true },
on: {
type: Schema.Types.ObjectId,
required: true,
// Instead of a hardcoded model name in `ref`, `refPath` means Mongoose
// will look at the `onModel` property to find the right model.
refPath: 'onModel'
},
onModel: {
type: String,
required: true,
enum: ['BlogPost', 'Product']
}
});
const Product = mongoose.model('Product', new Schema({ name: String }));
const BlogPost = mongoose.model('BlogPost', new Schema({ title: String }));
const Comment = mongoose.model('Comment', commentSchema);

How to achieve series of task using bluebird promise?

I've three models:
Users
Flats
Rooms
I want to get information(list) of those users who has no flat and has flat but has zero rooms (means room entry not found for particular flat).
User Model
username:{type: String},
password:{type: String},
...
Flat Model:
userid: { type: Schema.ObjectId, ref: 'User' },
flatname:{type: String}
...
Room Model:
roomid: { type: Schema.ObjectId, ref: 'Flat' },
roomnumber:{type: String}
...
I want to achieve this functionality using bluebird module promises.
I've already did :
var User = require('../models/User');
Promise.promisifyAll(User);
var Flat= require('../models/Flat');
Promise.promisifyAll(Flat);
var Room= require('../models/Room');
Promise.promisifyAll(Room);

Mongoose query from two schemas that share same reference

Suppose I have two schemas:
1. UserEnrolledCourses
var userCoursesSchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'users'},
courseId: { type: mongoose.Schema.Types.ObjectId, ref: 'courses'},
isEnrolled: Boolean,
});
2. CourseResources
var resourcesSchema = new mongoose.Schema({
courseId: { type: mongoose.Schema.Types.ObjectId, ref: 'courses', required: true },
type: {type:String, required:true},
});
Both of them shared the same courseId reference from courses schema.
So, my aim is to generate result from query that for each courseId that one user enrolled, list all of the resources that available. Is that possible?
In mongoDB, you are performing queries on one concrete collection. The only exception is the left outer join with new method $lookup in aggregation for mongodb 3.2 and more. Look at documentation

Resources