mongoose Foreign Key - mongodb

I have a model called Portfolio that points to a user object using the user_id field. How can I model a many to one relationship with mongoose?
Portfolio
- user_id => is the id of a user object
Basically every portfolio object belongs to a user object.
I have the following code: Is this correct?
var PortfolioSchema = mongoose.Schema({
url: String,
createTime: { type: Date, default: Date.now },
updateTime: { type: Date, default: Date.now },
user:[
{type: Schema.Types.ObjectId, ref: 'User'}
]
});

Try this instead
var PortfolioSchema = mongoose.Schema({
url: String,
createTime: { type: Date, default: Date.now },
updateTime: { type: Date, default: Date.now },
user:{type: Schema.Types.ObjectId, ref: 'User'}
});

Related

Referencing another collection Mongoose (MONGO)

If i have two Schema's as follows;
const userSchema = new mongoose.Schema({
telegramId: Number,
username: String,
balance: { type: Number, default: 0 },
totalTopUp: { type: Number, default: 0 },
totalRefunds: { type: Number, default: 0 },
totalOrders: { type: Number, default: 0 },
joined: Date,
});
const orderSchema = new mongoose.Schema({
orderId: String,
cardId: String,
userId: Number,
refunded: { type: Boolean, default: false },
baseId: String,
price: Number,
date: Date,
});
Where telegramId in userSchema and userId in orderSchema will match when a user makes an order, is it possible to have totalOrders in userSchema automatically update via some sort of referencing. Or will updates to totalOrders need to be made via code.
you can use post('save') middleware over orderSchema, on each new document you can increase the total orders.
https://mongoosejs.com/docs/api.html#schema_Schema-post

Select fields based on permission field

Hello guys i am having a problem getting from database only fields that are permitted by the user.
So my schema is:
var profileSchema = mongoose.Schema({
authId: {type: Schema.Types.ObjectId, ref: 'Auth'},
fname: String,
lname: String,
am: Number,
email: String,
location: String,
languages: [String],
birth_date: {
type: Date,
default: Date.now
},
reg_date: {
type: Date,
default: Date.now
},
last_log: {
type: Date,
default: Date.now
},
permissions: {
location: {type: Boolean,Default:true},
birth_date: {type: Boolean,Default:true},
email: {type: Boolean,Default:true},
am: {type: Boolean,Default:true},
subjects: {type: Boolean,Default:true},
files: {type: Boolean,Default:true},
posts: {type: Boolean,Default:true}
},
ip: String,
subjects: [{type: Schema.Types.ObjectId, ref: 'Subject'}],
files: [{type: Schema.Types.ObjectId, ref: 'FileIndex'}],
posts: [{type: Schema.Types.ObjectId, ref: 'Post'}],
notifications: [{type: Schema.Types.ObjectId, ref: 'Notifications'}]
});
And I am trying to get only fields that in permission field have true which means it's permitted. So I am running the following query :
database.Profile.findOne({_id: req.params.id}).exec(function (err, profile) {
console.log(profile);
res.send(profile);
});
How do I select only the fields that are permitted?
Try this, It ,might get you what you want:
database.Profile.findOne({_id: req.params.id},{location:$.permissions.location , birth_date:$.permissions.birth_date, email:$.permissions.email, am:$.permissions.am, subjects:$.permissions.subjects, files:$.permissions.files, posts:$.permissions.posts}).exec(function (err, profile) {
console.log(profile);
res.send(profile);
});
You could do a query with the lean() method chained since documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments and manipulate the object returned by removing the keys as determined by the permissions object fields:
Object.filter = function( obj, predicate) {
var result = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key) && !predicate(obj[key])) {
result[key] = obj[key];
}
}
return result;
};
database.Profile.findOne({_id: req.params.id}).lean().exec(function (err, doc) {
if (err) return handleError(err);
console.log(doc);
console.log(doc.permissions);
var filtered = Object.filter(doc.permissions,
function (key){ return doc.permissions[key]; }
);
console.log(filtered);
res.send(filtered);
});
Another alternative that uses the Mongoose's projection select() method would be to make two queries; the first one will return the whole document and the next will query the same document but project the fields based on the permissions object fields:
The following shows this:
database.Profile.findOne({_id: req.params.id}).lean().exec(function (err, doc) {
console.log(doc);
console.log(doc.permissions);
var projection = Object.keys(doc.permissions)
.filter(function (key){ return doc.permissions[key]; })
.join(' ');
console.log(projection);
database.Profile.findOne({_id: req.params.id})
.select(projection)
.exec(function (err, profile) {
if (err) return handleError(err);
res.send(profile);
});
});

How to count multiple query results

I have a document structure
var RelationshipSchema = new mongoose.Schema({
followee: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
follower: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
start: {
type: Date,
default: Date.now
},
end: {
type: Date
}
})
If i has a userId How would i query to count the followee and the follower for the same given userId.
and return the result?

2dsphere index on nested document not working

I wanted to save multiple locations in the below schema and run geolocation queries.
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Offer Schema
*/
var LocSchema = new Schema({
'type': {
type: String,
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [Number]
});
var LocationSchema = new Schema({
address:{type:String},
loc:[LocSchema]
});
var OfferSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Offer name',
trim: true
},
description:
{
type:String,
default:'',
required:'Please fill offer description',
trim: true
},
shortDesc:
{
type:String,
default:'',
trim: true
},
image:
{
type:String,
default:'',
required:'Please upload image'
},
locations:[LocationSchema],
created: {
type: Date,
default: Date.now
},
startDate: {
type: Date,
default: Date.now
},
endDate: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
category:
{
type: Schema.ObjectId,
ref :'Category'
}
});
OfferSchema.index({'locations.loc': '2dsphere'});
mongoose.model('Offer', OfferSchema);
When I run save on the object I get "something went wrong" error, however I am able to save the document if I delete the index.
Can someone tell me if I am doing something wrong.

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.