creating a reference document schema for mongoose and node.js - node.js

hi i am new to mongodb i am learning it and implementing for one of my hobby project which is using node.js ,please help me a schema and query to do the below project.
i have a hospital where each and every patient details are registered at his first visit and for every visit i need to add a visit for that patient by a reference like .
var patientschema=mongoose.schema(
{
objectid:"12345678"
patientname: string,
patientDOB:Date,
Gender:string,
registrationfee:number,
visits:[{objectid:1234},{objectid:5678}]
});
and visit schema is like
var visitschema = mongoose.schema({
objectid:"1234",
patientid:"12345678"
visitdate:date,
reason:string,
consultingdoctor:string
consultingfee:number
});
please provide me a proper schema and and a queries to achieve this from a node.js application.

In your case the two schemas should look like these.
var patientschema=mongoose.schema(
{
patientname: string,
patientDOB:Date,
Gender:string,
registrationfee:number,
visits:[{ type: mongoose.Schema.Types.ObjectId, ref: 'Visit' }]
});
var visitschema = mongoose.schema(
{
patientid:{ type: mongoose.Schema.Types.ObjectId, ref: 'Patient' }
visitdate:date,
reason:string,
consultingdoctor:string
consultingfee:number
});
var Visit = mongoose.model('Visit', visitschema);
var Patient = mongoose.model('Patient', patientschema);
Now let us create new Patient Entry:
var p1 = new Patient({name: 'Some Name', patientDOB : '2016-11-11', Gender : 'male', registrationfee : 123});
Now you can add Visits to this patient.
var v1 = new Visit({patientid : p1._id, ... Fill Other Fields here });
Now when save this visit, thats where it will get interesting
v1.save(function(err, res){
});
Mongoose will internally append v1's ID to your patient Visits Array. You can later search them by.
Patient.find().populate('visits').exec(function(err, res){
// Here the P1 with have array of Visits
});

Related

mongoose schema, is it better to have one or have several for different tasks?

so I'm been making a site that has comments section, messaging, profile and shopping for the user. I been wondering about when making a schema for those functions, is it better to have all in one schema like
userSchema {
name: String,
....
....
}
or have them seperate like
userSchema {
}
commentSchema {
}
gallerySchema {
}
No one can give you clear answer for this, everyone has different views.
Basically, It depends on your project's scalability
As I see your requirement for this project
You can create a single schema and use it as embedded form, but it's not a very good idea if you are scaling the app.
My recommendation is to create the separate schema for all the tasks which will be easy to debug,scaling the app and in readable form.
Edit
If you are creating separate schema and want to connect them then you can use populate on the basis of ObjectId
See the docs to populate collections
Example
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
Population
Story
.findOne({ title: 'Once upon a timex.' })
.populate('_creator')
.exec(function (err, story) {
if (err) return handleError(err);
console.log('The creator is %s', story._creator.name);
// prints "The creator is Aaron"
});

Updating a Record in Mongo After Retrieving Its ID From Another Record

I am trying to make an API point that would do the following. I submit an Object ID in the path. The record with that ID is found. Then, the program looks into a certain field of this object. The field contains an ObjectID for another entry in the database. At last, I need to pull up that record and increment a certain field in it.
In short, I have a child->parent relationship between certain records and would like the ability of incrementing a certain field within the parent record by submitting the child's id to the API point.
Here is the code I had that did the basic child increment. How can I go about doing it for the parent?
router.get('/today/parent/up/:id', function(req, res){
var collection = db.get('Activity');
collection.update({
_id: req.params.id
},
{
$inc: {
"repetitions.today": 1,
"repetitions.total": 1
}
}, function(err, activity){
if (err) throw err;
res.json(activity);
});
})
First use mongo references, heres documenttion:
https://docs.mongodb.com/manual/reference/database-references/
here's mongoose documentation
http://mongoosejs.com/docs/2.7.x/docs/populate.html
Basically You need to do this:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var PersonSchema = new Schema({
name : String
, age : Number
, stories : [{ type: Schema.ObjectId, ref: 'Story' }]
});
var StorySchema = new Schema({
_creator : { type: Schema.ObjectId, ref: 'Person' }
, title : String
, fans : [{ type: Schema.ObjectId, ref: 'Person' }]
});
var Story = mongoose.model('Story', StorySchema);
var Person = mongoose.model('Person', PersonSchema);
Then you could use .populate() method, and then you could extract your populated model and make changes and save them with .save(), but remember to use it in populated model, not the parent one. For ex. You've got author which contains reference to books, so you make request
author.findOne({'name': 'King'}).populate('books').exec((err, king) => {
let book0 = king.books[0];
book0.title = 'I need to change this one';
book0.save((err, data) => {
console.log('saved referenced object')
}
})

Nested objects are not update

Allora, I'm using mongoose for the first time and I decided to create 2 schemes: the first one represents a user and the second one represents his enquires. Users have an array of enquires like:
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [Enquire.schema] , "default" : [] },
});
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
I see that if I search for an enquire and update its status, it doesn't update the same enquire on the user's array, meaning that they are different object. I don't want to save an array of IDs as it will be the same as a relational database, so I see only 1 solution which is forgetting about the enquire scheme and use only the User scheme. Is it the way mongoose works? For every relationship do I have to insert everything like nested object?
I think you should use references to achieve what you want to achieve.
For more information on mongoose references and populate see Mongoose Populate documentation.
Try this, It may help you.
User Schema :
var userSchema = new mongoose.Schema({
name: String,
enquires: [{ type : mongoose.Schema.Types.ObjectId , ref : 'Enquiry' }]//array of enquiries
});
var User = mongoose.model('User',userSchema );
module.exports = User;
Enquiry Schema :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var Enquiry = mongoose.model('Enquiry',enquireSchema );
module.exports = Enquiry ;
Working :
create a new Enquiry.
Push it's ID(_id) into user's enquires array.
var enquiry = new Enquiry();
enquiry.enquire = "Dummy enquiry";//set the enquiry
enquiry.save(function(err,result){
if(!err){
//push 'result._id' into users enquires array
}
});
whenever you update an enquiry, it will be automatically updated in
user's document.
use populate to retrieve user's enquiries.
You can embed sub documents (entity) which has id and is like a document or embed native array like a normal property.
And I think the correct definition for yours is :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [enquireSchema] , "default" : [] },
});
If you use refs in embedded link then there are two separate collections and be like relational db's.

How should I approach my back end design using the MEAN stack?

This is maybe more a case of looking for advice. However, I will supply sample code as an example of what I want to achieve. I am trying to build my first back end system and I keep running into problems with the design.
My MongoDB database consists of 4 major parts - Profiles, Teams, Drafts and Users. The profile (being the main data which sources everything using IDs) schema has properties to hold arrays with the Teams and Drafts IDs. The idea is that when the profile is served it will populate all those properties with the relevant data by using the IDs.
Example of the Profile schema using Mongoose:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserProfileSchema = new Schema({
Name : String,
Email : String,
Admin : Boolean,
Status : Number,
UserID : String,
PrivateProfile: Boolean,
Drafts: [String], //This array holds the draft IDs
Teams:[String] //Holds the team profiles IDs
});
module.exports = mongoose.model('UserProfile', UserProfileSchema);
Example of Team Profile Schema using Mongoose:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TeamProfileSchema = new Schema({
Name : String,
CaptainID : String,
CaptainName : String,
Members : [String], //Array of user IDs
DateCreated : Boolean,
Reputation : Number
});
module.exports = mongoose.model('TeamProfile', TeamProfileSchema);
Example of a route to find all the Team Profiles the user is the Captain of and fetch all the members associated with that team:
router.route('/teams/captain/:user_id')
.get(function (req, res) {
TeamProfile.find({
CaptainID : req.params.user_id
}, function (err, teams) {
if (err)
res.send(err);
for (var x in teams) {
var membersArray = [];
for (var i in teams[x].Members) {
var ID = teams[x].Members[i];
UserProfile.find({
UserID : ID
}, function (err, profile) {
if (err)
res.send(err);
membersArray.push(profile);
});
}
teams[x].Members = membersArray;
console.log(teams[x].Members);
}
res.json(teams);
});
})
I understand that the route will not work, but how do I pull this off? I used a more vanilla approach only for the purpose to explain what I want to achieve. Any help would be highly appreciated.
I advise you to use combination of denormalization and normalization.
because MongoDB is not a relational database.
denormalization is much faster then normalization. You don't need to use relationship anymore.
You can read this article hope may helpfull to you.
Cheers

Does mongoose / mongodb have access to object references in schema during aggregate?

I'm working on a query that reads from 2 different obj referentes inside my mongo database. I will use a simple example of what im looking for.
I have 3 schemas:
User = new Schema({
places:[{type: Schema.Types.ObjectId, ref:'Place'}],
shouts:[{type: Schema.Types.ObjectId, ref:'Shout'}]
});
Place = new Schema({
name:String,
description:String,
});
Shout = new Schema({
content:String,
});
My biggest question is if mongoose or mongodb has access to objectId references when executing the aggregate method. Allow me to elaborate.
module.exports.askForShoutInPlace = function(req, res){
var pname = new RegExp(req.params.pname, 'i');
User.aggregate(
[
{'$match':{ 'places':{
'$elemMatch':{'name':pname}
}
},
{'$project':{ shout:'$shouts'} },
{'$unwind':'$shouts'},
{'$group':{_id:'$shouts'}}
]).exec(function(err, results){
res.send(results);
});
}
That usually works fine, however I'm getting an empty array once the $match operator is called, im guessing it has to do with the object references returning undefined subobjects. is there any work around this? or does this mean I have to take another route to employ populating?
thanks for all the help in advance
there's no way to access object Referenced data during the aggregate Process, the work around I employed for my project was to add a reference to the owner in the schemas in question.
User = new Schema({
places:[{type: Schema.Types.ObjectId, ref:'Place'}],
shouts:[{type: Schema.Types.ObjectId, ref:'Shout'}]
});
Place = new Schema({
owner:{type: Schema.Types.ObjectId, ref:'Place'},
name:String,
description:String,
});
Shout = new Schema({
owner:{type: Schema.Types.ObjectId, ref:'Place'},
content:String,
});
And then employed to Aggregate directly on the subdocument to obtain the unique users who own the instances of of place, this way I can obtain a shout result matching a query and a place.
Example:
module.exports.askForShoutInPlace = function(req, res){
var pname = new RegExp(req.params.pname, 'i');
var stringQ = new RegExp(req.paramos.qcontent, 'i');
Place.aggregate(
[
//find Places that match criteria
{'$match':{'name':pname}},
//select owner id object to result
{'$project':{ owner:'$owner'}},
//group those results to single array with unique ids of users
{'$group':{_id:'$owner'}}
]).exec(function(err, results){
//find user shouts that match string and belong to owners know to be owners of a place
Shout.find({'content':stringQ}).where({'owner':{'$in':results}}).exec(function(err, shouts){
res.send(shouts);
});
});
}
this is just the way I found to work around my particular needs, I hope it might help somebody.

Resources