Mongo Relationships/Referencing - node.js

I am new to MongoDB references. Right now I have one collection which I call users. It stores all users and their keys. I have another collection which has data for each key.
I want to just use their key as the ID to connect them. So I will have each key generated and and the keyData will be empty when first created and then I will just keep adding objects to the keyData array. That is my plan, but I do not know how I create the relation with the schema.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//Create Schema
const userKey = new Schema({
_id : {
type : String,
required: true
},
key: {
type : String,
required: true
},
keyData: [key],
date: {
type: Date,
default: Date.now
}
});
module.exports = Key = mongoose.model('key', userKey);
This doesn't work because I cannot access the key before initialization. So how canI relate the two collections?

Schema #1: userData
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create User-data Schema
const userData = new Schema({
data: {
type: Array,
require: true
}
},
{
collection: 'data' // Mentioning collection name explicitly is good!
});
module.exports = mongoose.model('data', userData);
Schema #2: Keys
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create User-Key Schema
const userKey = new Schema({
key: {
type: String,
required: true
},
keyData: {
type: Schema.Types.ObjectId,
ref: 'data'
},
date: {
type: Date,
default: Date.now
}
},
{
collection: 'keys' // Mentioning collection name explicitly is good!
});
module.exports = mongoose.model('keys', userKey);
As per this link its not possible to set string as refs. So in your keys schema use ObjectId as ref.

Would something like this work?
const userData = new Schema({
_id : {
type : String,
required: true
},
data : {
type : Array,
require: true
}
});
const userKey = new Schema({
_id : {
type : String,
required: true
},
key: {
type : String,
required: true
},
keyData: [{ type: Schema.Types.ObjectId, ref: 'data' }],
date: {
type: Date,
default: Date.now
}
});
module.exports = KeyData = mongoose.model('data', userData);
module.exports = Key = mongoose.model('key', userKey);

Related

How to rename a collection without loosing data of collection in Mongoose

I am using Mongoose in my NodeJs project. I want to rename my collection from OldCollectionName to NewCollectionName.
I tried following:
Mongoose.connection.collection('OldCollectionName').rename('NewCollectionName');
But this is making my collection empty. Can someone suggest how can I change the collection name without loosing my collection data? I need all the data from OldCollectionName in NewCollectionName as well.
I have following schema for my model
const Mongoose = require('mongoose');
const mongooseSequence = require('mongoose-sequence');
const Schema = Mongoose.Schema;
var collectionSchema = new Schema({
collectionIdAutoIncrement: { type: Number,unique: true,index:true,sparse:true},
fieldName: {
type: String,
default: ''
},
otherCollectionId: {
type: Schema.Types.ObjectId,
required: true,
ref: "OtherCollection",
},
created: { type: Date, default: Date.now },
updated: { type: Date},
});
collectionSchema.plugin(mongooseSequence, { inc_field: 'collectionIdAutoIncrement' });
var oldCollection = Mongoose.model('OldCollectionName', collectionSchema);

MongoDB Auto-increment for a nested Object in a document in Node.js

I've a schema in Mongo like below:
({
title: String,
genre: String,
publishDate: Date,
index:Number,
requirementInformation:{
requirementInformationStatus:{
type: String,
required: true
},
requirement: [{ requirementId: {
type: Number
},requirementState: {
type: String
}}]
}
})
I want to Auto-increment the field requirementId in Node.js. I tried using mongoose-auto-increment package but not able to create the Auto-increment for the nested Object. Need some help.
My code is as below:
const mongoose = require('mongoose')
const Schema= mongoose.Schema;
var autoIncrement = require('mongoose-auto-increment');
var connection = mongoose.createConnection("mongodb://localhost/Test");
autoIncrement.initialize(connection);
var bookSchema = new Schema({
title: String,
genre: String,
publishDate: Date,
index:Number,
requirementInformation:{
requirementInformationStatus:{
type: String,
required: true
},
requirement: [{ requirementId: {
type: Number
},requirementState: {
type: String
}}]
}
});
bookSchema.plugin(autoIncrement.plugin, {model:'Book',field: 'requirementInformation.requirement.requirementId'});
//authorSchema.plugin(autoIncrement.plugin, 'Author');
var Book = connection.model("Book", bookSchema);
const me = new Book({
title: 'MyBook',
requirementInformation:{requirementInformationStatus:'True',requirement:[{requirementState:"hj"}]}
})
me.save().then(() => {
console.log(me)
}).catch((error) => { console.log(error) })
How can I access the requirementId field?

node mongoose update two collections

I have two schemas, a "projects" schema, and an "applications" schema.
What is the most efficient way of creating a new entry in a collection and updating an existing entry in another collection based on data inside the new entry? Can I avoid making multiple API requests and somehow run a "stored procedure" on the mongoDB end to handle updating the Projects collection when there is a change in the Applications collection?
In this scenario, ideally when an application for a project is created, a new entry is created in the Applications collection and the Project in the Projects collection is updated to reflect the information in the Application.
Can I do this without making multiple api requests?
Project Schema:
// models product.js
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Schema;
const projectSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlength: 32
},
applications: {
type: Number,
default: 0
},
created_by: {
type: ObjectId,
ref: 'User'
},
applicants: {
type: Array,
default: []
}
}, {timestamps: true}
);
module.exports = mongoose.model("Project", projectSchema);
Application Schema:
const mongoose = require('mongoose');
const applicationSchema = new mongoose.Schema({
applicantId: {
type: ObjectId,
ref: 'User'
},
ownerId: {
type: ObjectId,
ref: 'User'
},
projectId: {
type: ObjectId,
ref: 'Project'
}
}, {timestamps: true});
module.exports = mongoose.model("Application", applicationSchema);
Note that these are separate schemas because they each carry around 15 fields, i've trimmed them down to post this question.
I suggest to use hooks for mongoose model, there is a post save hook which you can use on Application model to update Project and increment application count.
EDIT - Added Pseudo Code
Project Model
// models -> project.js
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.Schema;
const projectSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlength: 32
},
applications: {
type: Number,
default: 0
},
created_by: {
type: ObjectId,
ref: 'User'
},
applicants: {
type: Array,
default: []
}
}, {
timestamps: true
});
projectSchema.statics = {
/**
* Find project by _id
*
* #param {ObjectId} _id
* #api private
*/
get: function (_id) {
return this.findOne({
_id
})
.exec();
}
}
module.exports = mongoose.model("Project", projectSchema);
Application Model
const mongoose = require('mongoose');
const projectModel = require("./project")
const applicationSchema = new mongoose.Schema({
applicantId: {
type: ObjectId,
ref: 'User'
},
ownerId: {
type: ObjectId,
ref: 'User'
},
projectId: {
type: ObjectId,
ref: 'Project'
}
}, {
timestamps: true
});
// Async hook
applicationSchema.post('save', function (doc, next) {
const relatedProject = projectModel.get(doc.projectId);
relatedProject.applications++;
relatedProject.save();
next();
});
module.exports = mongoose.model("Application", applicationSchema);

How do I index a field on a mongoose Schema that uses a discriminator?

The error started after I started using the discriminator.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Base = require("../config/Base");
const Refill = Base.discriminator(
"Refill",
new Schema({
cylinderSize: { type: Number, required: true },
cylinderSwap: { type: Boolean, required: true },
quantity: { type: Number, required: true },
location: {
type: { type: String },
coordinates: [Number]
}
})
);
Refill.index({ location: "2dsphere" });
module.exports = mongoose.model("Refill");
This returns the error Refill.index is not a function
In Mongoose, indexes must be created on schemas, not models. In your case, the Refill object is a model. One approach is to implement this in three steps:
Create the schema
Add the index to the schema
Create the model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Base = require("../config/Base");
const refillSchema =
new Schema({
cylinderSize: { type: Number, required: true },
cylinderSwap: { type: Boolean, required: true },
quantity: { type: Number, required: true },
location: {
type: { type: String },
coordinates: [Number]
}
});
refillSchema.index({ location: "2dsphere" });
const Refill = Base.discriminator("Refill", refillSchema);
module.exports = mongoose.model("Refill");
I just took out the Refill.index({ location: "2dsphere" }); and the rest of my code is working fine apparently indexing that field wasn't necessary.

Nodejs Mongoose : ref on another propertiy

I`m trying create ref from one collection to another collection but not with ref on id.
For example: I have two schema, user and foo. Foo has one unique property 'name'.
USER
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
username: {
type: String,
require: true
},
foo: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Foo'
}
});
mongoose.model('User', userSchema);
FOO
const mongoose = require('mongoose');
const fooSchema = mongoose.Schema({
name: {
type: String,
require: true,
index: {
unique: true
}
}
});
mongoose.model('Foo', fooSchema);
This is work perfect, but can I do ref on that unique property (not on _id)? Like this:
const userSchema = mongoose.Schema({
username: {
type: String,
require: true
},
foo: {
type: String,
property: 'name',
ref: 'Foo'
}
});
Thanks for any answers ;)

Resources