How do you set-up a mongoose column from schema A to have the values from a column from schema B? - mongodb

I have
schema A:
let informationAssetsRow = new Schema({
infAss: {
type: String
})
Schema B
let informationAssetsSeverityEvaluationRow = new Schema({
Informationasset: {
type: String
}
})
For the sake of simplicity I have removed other attributes.
What I would like to do is:
Each time a document inserted in collection A. I want the value of infAss to be also inserted in Informationasset in column B.
From SQL perspective, this seems to be infAss of collection A should be set-up as an external key to schema B. I'm not sure I'm right.
However, in mongodb it's not clear if that is doable.
Any help?

You can create a post('save') hook on informationAssetsRow schema to achieve what you want.
Everytime a new document is inserted in collection A, post save hook will save new document into collection B.
Try this:
informationAssetsRow.post('save',function(doc){
informationAssetsSeverityEvaluationRow.create({
Informationasset : doc.infAss
})
})
Read more about Mongoose Post Hooks for detailed information.

Related

What is the difference between mongoose.ObjectId and mongoose.Types.ObjectId?

It's mentioned in the docs the following:
An ObjectId is a special type typically used for unique identifiers...
const carSchema = new mongoose.Schema({ driver: mongoose.ObjectId });
ObjectId is a class, and ObjectIds are objects....etc
const Car = mongoose.model('Car', carSchema);
const car = new Car();
car.driver = new mongoose.Types.ObjectId();
typeof car.driver; // 'object'
car.driver instanceof mongoose.Types.ObjectId; // true
car.driver.toString(); // Something like "5e1a0651741b255ddda996c4"
What is meant by ObjectId (the bold text above in the quote)? is it mongoose.ObjectId or mongoose.Types.ObjectId?
And what's the difference between them?
The URL of the docs:
https://mongoosejs.com/docs/schematypes.html#usage-notes
at the ObjectIds section
According to schema types docs
A SchemaType is different from a type. In other words, mongoose.ObjectId !== mongoose.Types.ObjectId. A SchemaType is just a configuration object for Mongoose. An instance of the mongoose.ObjectId SchemaType doesn't actually create MongoDB ObjectIds, it is just a configuration for a path in a schema.
Also into docs:
You can think of a Mongoose schema as the configuration object for a Mongoose model. A SchemaType is then a configuration object for an individual property. A SchemaType says what type a given path should have, whether it has any getters/setters, and what values are valid for that path.
So, mongoose.Types.ObjectId is a "mongoose object" while mongoose.ObjectId is a "mongodb object".
Edit to answer the comments.
To the first question, for me is: Yes. As a developer that use mongoose I only use mongoose functions. That implies use mongoose.Types.ObjectId instead of mongoose.ObjectId.
Also if you try to do mongoose.ObjectId() you will get a warning 'To create a new ObjectId please try Mongoose.Types.ObjectId instead of using Mongoose.Schema.ObjectId'
About the second question, if I've understood correctly, yes too. You can check this.
Create a new schema and do:
const MongooseModel = new mongoose.Schema({_id: mongoose.Types.ObjectId})
MongooseModel.path('_id') instanceof mongoose.Schema.ObjectId // true
MongooseModel.path('_id') instanceof mongoose.SchemaTypes.ObjectId // true
MongooseModel.path('_id') instanceof mongoose.Schema.Types.ObjectId // true
MongooseModel.path('_id') instanceof mongoose.ObjectId // true
MongooseModel.path('_id').instance // ObjectID
MongooseModel.path('_id') instanceof mongoose.Types.ObjectId // false
mongoose.Schema.ObjectId instanceof mongoose.Types.ObjectId // false
Your schema _id is created via mongoose.Types and is instance of mongoose.ObjectId. Also is not an instance of the type, as explained into docs "A SchemaType is different from a type".
The _id generated is an instance of the ObjectID but is not an instance of the "parent" who generates the value.
So in other words, we developers only use mongoose.Types.ObjectId, while mongoose.ObjectId is in most of the time only consumed by mongoose and not by us. correct me if I'm misunderstanding it, have you ever used mongoose.ObjectId? if yes, in which scenarios? – Ekmek
Ekmek - I have some experience with this. The reason for the mongoose object Id in this way is to 'pre-fetch' a unique id. Instead of waiting for mongodb to take the new doc and issue an Id, we can use mongoose to create a key for us and save the waiting step. This is useful when you want the new id but don't have time to wait for mongodb to give you one. ...I just can't remember if I had to configure something to tell mongodb not to worry.

Populate a query in Mongoose with Schema First approach and NestJS

First off I want to say this question is similar to this one which references this one. I have the exact same question as the second link except a notable difference. I'm trying to extend a class generated by NestJS which defines a property.
I'm using NestJs with the Schema first approach found here. I'm also generating a classes file based on my GraphQL Schema.
Here is the Schema:
type Location {
name: String!
owner: User!
}
Which generates the class:
export class Location {
name: string;
owner: User;
}
Now, I want to extend this class so I don't have to repeat the data (there are a lot more fields not shown). I also I want to add fields that live on a document but are not in the schema (_id in this example). Here is my LocationDocument and my schema.
export interface LocationDocument extends Location, Document {
_id: Types.ObjectId
}
export const LocationSchema: Schema = new Schema(
{
name: {
type: String,
required: true,
},
owner: {
type: Types.ObjectId,
ref: 'User',
}
);
Now here is my issue. The generated Location class from the GraphQL schema defines the owner property as a User type. But in reality it's a just a mongodb id until it is populated by Mongoose. So it could be a Types.ObjectId or a User on a UserDocument. So I attempted to define it as:
export interface LocationDocument extends Location, Document {
_id: Types.ObjectId
owner: User | Types.ObjectId;
}
But this throws an error in the compiler that LocationDocument incorrectly extends Location. This makes sense. Is there any way to extend the User Class but say that owner property can be a User Type (once populated by Mongoose) or a mongo object ID (as is stored in the database).
I decided that having a property that can be both types, while easy with Mongoose and JS, isn't the typed way. In my schema I have an owner which is a User type. In my database and the document which extends it, I have an OwnerId. So to people accessing the API, they don't care about the ownerId for the relationship. But in my resolver, I use the Id. One is a Mongo ID type, the other is a User type.

Mongoose - Restrict the fields on referenced model

I have users model that can hold multiple notifications. In the NotificationSchema the notifier holds users ID and it references the users model. When I execute the following query :
User.find().populate('notifications.notifier').exec(function(err,users){
//users[0].notifications[0].notifier
//I am getting all fields from the referenced user
//I don't want the whole document but some fields only
});
How can someone Limit / Restrict the fields that should be available while referencing to some model.
Here is the users model
var NotificationSchema =new Schema({
notifier : {type:Schema.Types.ObjectId, ref:'users'},
//How could I say :
//notifier : {type:Schema.Types.ObjectId, ref:'users', fields:['_id', 'name']}
//because I know what fields do I need from referenced model for this Schema.
__SOME__
__OTHER__
__FIELDS__
});
var UsersSchema = new Schema({
name : {given:String, middle:String, family:String}
email:String,
password:String,
notifications : [NotificationSchema]
});
var Users = mongoose.model('users', UsersSchema);
BTW, I do not have separate model for NotificationSchema.
If this feature is not available out of the box how could I implement it manually. Am I missing some docs? Please let me know the robust way of doing it.
I found it in mongoose docs
I found the answer in Field Selection Section of the documentation
User.find().populate('notifications.notifier', '_id name').exec(function(err, users) {
//users[0].notifications[0].notifier ^^^^^^^^^ HOW FUNNY
//Yes I am getting '_id' and 'name' fileds only
});

How to update nested object field in MongoDB document via Mongoose Node.js ORM?

I can't figure out how to change the value of a field in a nested document in a MongoDB document via the Mongoose Node.js JavaScript ORM. Code in CoffeeScript:
mongoose = require 'mongoose'
mongoose.connect 'mongodb://localhost/test'
Schema = mongoose.Schema
Page = new Schema
content: String
Article = new Schema
_id: String
pages: [Page]
article_model = mongoose.model 'Article', Article, 'testcollection'
article_model.findOne({_id: 'id1'}, (err, article) =>
article.pages[0].content = 'foo'
article.save()
)
The next time I fetch article, article.pages[0].content still has its original value, although there is no error on the save().
I suspect I need to reference content differently... but how? Thanks!
Edit: It works if I do something like this:
for page in article.pages
if page is whatever
page.content = 'foo'
article.save()
However, that seems pretty inelegant and inefficient.
You have to use the update function.

Node + Mongoose: Get last inserted ID?

I want to retrieve the last inserted _id, using mongoose as MongoDB wrapper for node.js. I've found the following tutorial, but I can't change any node modules because the app runs on a public server:
Getting "Last Inserted ID" (hint - you have to hack Mongoose)
Any other ideas? This what I want to do:
Insert new user
Get user's _id value
Set a new session based on user's id
Redirect to /
Thanks!
I'm using mongoose version 1.2.0 and as soon as I created a new instance of a mongoose model, the _id is already set.
coffee> u = new User()
[object Object]
coffee> u._id
4dd68fc449aaedd177000001
I also verified that after I call u.save() the _id remains the same. I verified via MongoHub that this is indeed the real ID saved into MongoDB.
If you explicitly declare
_id: Schema.ObjectId
for your model, then the ObjectId will not be available after new or save.
This is probably a bug.
If you're looking to get the last inserted _id of a sub object, then create the object, and add it to the item. Here's an example in NowJS using MongoDB and Mongoose (to add some schema sugar) which then converts the result to JSON to send back to the client:
var nowRoomID = this.now.room;
var Conversation = mongoose.model('Conversation');
Conversation.findById(convID, function(error, conversation) {
var Blip = mongoose.model('Blip');
var createdBlip = new Blip();
createdBlip.author= nowUserName;
createdBlip.authorid = parsed.authorid;
createdBlip.body = revisedText;
createdBlip.created_at = new Date();
createdBlip.modified_at = new Date();
conversation.blips.push(createdBlip);
parsed._id = createdBlip._id; //NOTE: ID ACCESSED HERE
message = JSON.stringify(parsed);
conversation.save(function (err) {
if (!err) {
console.log('Success - saved a blip onto a conversation!');
nowjs.getGroup(nowRoomID).now.receiveMessage(nowUserName, message);
}
});
With MongoDB, if you don't explicitly set a document's _id value then the client driver will automatically set it to an ObjectId value. This is different from databases that might generate IDs on the server and need another query to retrieve it, like with SQL Server's scope_identity() or MySQL's last_insert_id().
This allows you to insert data asynchronously because don't need to wait for the server to return an _id value before you continue.
So, as shown is Peter's answer, the _id is available before the document is saved to the database.
I just get the id from the document passed to the callback, since save returns the saved document.
Check below url
http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
you will find following code in given url
var document = {name:"David", title:"About MongoDB"};
collection.insert(document, {w: 1}, function(err, records){
console.log("Record added as "+records[0]._id);
});