Index containing multiple fields in MongoDB - mongodb

In MongoDB, How do i restrict the data entry bases on 3 fields RegisterUserId ,PageId and IsFavourite. None of them is unique?
what should the query be?
Below is my Schema
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});
module.exports = mongoose.model('t_FavMaster', FavMasterSchema);

Try this:
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});

Related

Collection referencing multiple collections

I want to have a collection with multiple fields referencing multiple collections, something like it:
var comboSchema = new Schema({
oneId: { type: Schema.Types.ObjectId, ref: "One" },
twoId: { type: Schema.Types.ObjectId, ref: "Two" },
threeId: { type: Schema.Types.ObjectId, ref: "Three" },
components: {
id: {type: Schema.Types.ObjectId, ref: "Component"},
amount: {type: Number}
}
}
I know I can use $lookup and aggregate to get data, but it looks like it works only on a single field in a collection?
Any help? Thank you! :-)
This is a model sample using the ref, the ref key in the object will take the name of the model in which you are referencing
const mongoose = require('mongoose');
const postSchema = mongoose.Schema({
text: {
type: String,
required: 1
},
mediatype: {
type: String,
required: 1
},
media: {
type: String,
required: true
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
likes: {
type: [{
userid: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}
}]
},
comments: {
type: [{
userid: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
comment: String
}]
},
}, {
timestamps: true
})
const Post = mongoose.model('post', postSchema)
module.exports = Post
so you can then populate it like Post.find().populate('user')

Mongoose Populate ignored for this basic setup

I have a User Schema, which has multiple notes, and the Note which belongs to a userId
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'Note'}]
});
const NoteSchema = new Schema({
userId: {type: mongoose.Types.ObjectId, ref: 'User'},
content: {type: String, required: true, trim: true, lowercase: true},
});
I'm trying to populate my User with the notes using the following syntax (from the docs)
const user = await User.findById(mongoose.Types.ObjectId("5bd2a8c4963ac00f57a18074"))
.populate('notes')
.exec(function (err, result) {
console.log(result);
});
But it's returning the User without the Notes data. Any idea what I might be doing wrong?
NoteSchema here is the problem:
userId: {type: mongoose.Types.ObjectId, ref: 'User'}
Use below,
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.ObjectId, ref: 'User'} // For backword compatibility
Note:- The schema should always use mongoose.Schema.Types. And mongoose.Types.ObjectId can be used withing mongoose implementation.
I am able to get document properly (Below code):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
const NoteSchema = new Schema({
userId: {type: Schema.Types.ObjectId, ref: 'UserTest'},
content: {type: String, required: true, trim: true, lowercase: true},
});
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'NoteTest'}]
});
var Note = mongoose.model('NoteTest', NoteSchema);
var User = mongoose.model('UserTest', UserSchema);
User.find({_id : mongoose.Types.ObjectId("5bd2c84dd79cc5d8b1c62964")})
.populate('notes')
.exec(function (err, result) {
console.log("result.....", JSON.stringify(result));
});
Output:
[
{
"_id": "5bd2c84dd79cc5d8b1c62964",
"email": "hardik#com.com",
"notes": [
{
"_id": "5bd2c869d79cc5d8b1c62965",
"content": "ABC",
"userId": "5bd2c84dd79cc5d8b1c62964"
},
{
"_id": "5bd2c88ad79cc5d8b1c62966",
"content": "DEF",
"userId": "5bd2c84dd79cc5d8b1c62964"
}
]
}
]

Update field in another schema with post hook mongoose

I have that schemas:
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
module.exports = mongoose.model('OrderDetail', schema);
and
var schema = new Schema({
name: {type: String, required: true},
price: {type: Float, required: true},
idProvider: {type: Schema.Types.ObjectId, ref: 'Provider'},
idProduct: {type: Schema.Types.ObjectId, ref: 'Product'},
description: {type: String},
quantitySold: {type: Number}
});
module.exports = mongoose.model('ProdProv', schema);
I need to update field "quantitySold" when a post.save happens in order-detail, i've tried this:
schema.post('save', function(next){
//But this point I can't find the prodprov to update field
})
How I can do this?
Thank you.
Thank you #mjim, but that´s code not works. I've modify the code and works! this is my solution:
schema.post('save', function(doc){
var prod = ProdProv.findById(this.prodprov).exec().then((pp) => {
pp.quantitySold += this.quantity;
pp.save();
});
});
I would suggest:
var ProdProv = require('./ProdProv');
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
schema.post('save', async function(doc){
var prod = await ProdProv.findById(doc.prodprov);
prod.quantitySold = doc.quantity;
prod.save()
});
module.exports = mongoose.model('OrderDetail', schema);

.where() by populated fields

I want to find the closest workers by his location which have a specific skill.
Location schema:
var schema = Schema({
name: String,
type: String, // home | latest
user: {type: Schema.Types.ObjectId, ref: 'User'},
address: String,
position: {
type: {type: String, default: 'Point'},
coordinates: [Number]
},
status: String // active | inactive
}, {collection: 'locations'});
Worker schema:
var schema = Schema({
username: String,
password: String,
firstName: {type: String, default: ''},
middleName: {type: String, default: ''},
lastName: {type: String, default: ''},
role: {type: String, default: 'user'}, // admin | user | worker
skills: [{
object: {type: Schema.Types.ObjectId, ref: 'Skill'},
slug: String, // Should remove in the future
ratePerHour: Number,
status: {type: String, default: 'active'} // active | inactive
}],
locations: [{type: Schema.Types.ObjectId, ref: 'Location'}]
}, {collection: 'users'});
Skill schema:
var schema = Schema({
name: String,
slug: String,
users: [{type: Schema.Types.ObjectId, ref: 'User'}],
isFeatured: Boolean,
minRatePerHour: Number,
maxRatePerHour: Number,
status: String // active | inactive | deleted
}, {collection: 'skills'});
Bellow is my query but .where() does not work with populated field.
Location
.find({
'position': {
$near: {
$geometry: {type: 'Point', coordinates: [lat, lng]},
$minDistance: 0,
$maxDistance: 20000
}
}
})
.populate('user')
.deepPopulate('user.skills.object')
.where({'user.skills': {$elemMatch: {'object.slug': 'cleaning'}}})
.limit(5)
.exec(callback);
Am I doing wrong with these schemas? Should I use embed document rather than ID reference?
Is there any way else to query?
You have to use special properties for populate as described here: Query conditions and other options
So I think you can get your results with something like this:
Location
.find({
'position': {
$near: {
$geometry: {
type: 'Point',
coordinates: [lat, lng]
},
$minDistance: 0,
$maxDistance: 20000
}
}
})
.populate({
path: 'user',
match: {
'skills': {
$elemMatch: {
'object.slug': 'cleaning'
}
}
},
options: {
limit: 5
}
})
.deepPopulate('user.skills.object')
.exec(callback);
Not tested, keep it only as example.

Population to sub-scheme in Mongoose

I have two schemas:
Clinic:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ProcedureSchema = mongoose.Schema({
name: {
type: String,
trim: true,
required: true
},
alias: {
type: String,
trim: true,
required: true
}
});
var ClinicSchema = mongoose.Schema({
name: {
type: String,
trim: true,
required: true
},
procedures: [ProcedureSchema]
});
module.exports = mongoose.model('Clinic', ClinicSchema);
and Record:
var mongoose = require('mongoose'),
Patient = require('./patient'),
User = require('./user'),
Clinic = require('./clinic'),
Schema = mongoose.Schema;
var RecordSchema = Schema({
doctor: {
type: Schema.Types.ObjectId,
ref: 'User'
},
clinic: {
type: Schema.Types.ObjectId
},
date: {
type: Date
},
patient: {
type: Schema.Types.ObjectId,
ref: 'Patient'
},
procedure: {
type: [Schema.Types.ObjectId],
ref: 'Clinic'
}
});
module.exports = mongoose.model('Record', RecordSchema);
In record schema i store all ids of procedure, which sub-scheme for Clinic
I want to get full object of procedures in record.
I try this query:
Record.find({}).
populate('procedures.procedure').
populate('doctor').
populate('patient').
exec(function(err, records) {
...
});
But get only array of ids, instead array of objects.
Where is problem?
You totally mix all schemes:
populate('procedures.procedure')
But you have not procedures in RecordSchema. Even if it is type mistake, an you mean procedure.procedures - you don't have procedures in ProcedureSchema.
read more about references in MongoDB especially http://docs.mongodb.org/manual/applications/data-models-tree-structures/
Try to make nesting path less than 2. Something like this:
var User,
Procedure,
Clinic,
Patient,
Record;
function defineModels(mongoose, fn) {
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
User = new Schema({
...
});
Procedure = new Schema({
name: { type: String, trim: true, required: true },
alias: { type: String, trim: true, required: true }
});
Clinic = new Schema({
name: { type: String, trim: true, required: true },
procedures: [ProcedureSchema]
});
Patient = new Schema({
...
});
Record = new Schema({
'date': {type: Date, default: Date.now},
'doctor': {type: ObjectId, ref: 'User'},
'clinic': {type: ObjectId, ref: 'Clinic'},
'patient': {type: ObjectId, ref: 'Patient'},
'procedure': {type: ObjectId, ref: 'Procedure'},
});
mongoose.model('User', User);
mongoose.model('Procedure', Procedure);
mongoose.model('Clinic', Clinic);
mongoose.model('Patient', Patient);
mongoose.model('Record', Record);
fn();
}
exports.defineModels = defineModels;
Hope this help.