Mongoose - save object with objectid - javascript

Here I have two schema:
var personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
job: {
type: Schema.Types.ObjectId,
ref: 'Job',
}
});
var jobSchema = Schema({
_id: Schema.Types.ObjectId,
title: String,
});
var Job = mongoose.model('Job', jobSchema);
var Person = mongoose.model('Person', personSchema);
Suppose Job has some records:
[{
"_id" : ObjectId("5b46d41e04cfc922949dcfda"),
"Title": "Teacher"
}, ...]
When I have some person objects to insert:
[{
name: 'Peter',
job: 'Teacher'
}, ...]
Do I need to find the Job's _id and convert the job field to ObjectId type before each save? e.g.
Job.findOne({title: p.job}, (j) => {
Person.save({name: p.name, job: j._id}).exec(()=>{
// it's ok!
)}
})
Or I can use the middleware or populate function to make it easy? Thankyou!

While saving your person , you are needing a job for it.
So this is how you can proceed for the same:
Either create a new job / find an existing job.
Assign the found job's objects _id field to your new Person and save the same.
Eg.code
let person = new Person({
name : 'TszHin'
});
Job.findOne({ title : 'Abc'})
.then(function(job){
person.job = job._id;
person.save();
});

Related

Mongoose - Model.updateOne isn't working for me when adding an embeded document to an existing document

When I run this code in node.js my embedded document id doesn't match with the related id in the other collection.
const fruitSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
rating: {
type: Number,
min: 1,
max: 10,
},
review: String
});
const Fruit = mongoose.model("Fruit", fruitSchema);
const watermelon = new Fruit({
name: "Watermelon",
rating: 7,
review: "Meh."
});
// watermelon.save();
const personSchema = new mongoose.Schema({
name: String,
age: Number,
favouriteFruit: fruitSchema
});
const Person = mongoose.model("Person", personSchema);
const person = new Person({
name: "John",
age: 37,
favouriteFruit: watermelon
});
person.save();
As a result, in MongoDB I get, From
db.fruits.find()
{
"_id" : ObjectId("5e7444c37ce78dd238d0f994"),
"name" : "Watermelon",
"rating" : 7,
"review" : "Meh.",
"__v" : 0
}
From
db.people.find()
{
"_id" : ObjectId("5e7451d971df90096974be01"),
"name" : "John",
"age" : 37,
"favouriteFruit" :
{
"_id" : ObjectId("5e7451d971df90096974be00"),
"name" :"Watermelon",
"rating" : 7,
"review" : "Meh."
},
"__v" : 0
}
I think I'm missing something with the Model.updateOne method.
I'm just trying to add an embedded document into another document.
I'm just a beginner, so any links or help would be amazing!
Thanks!
Why such behavior?
The reason you are having different _ids in the two fruits object that are supposed to be the same is that you did not add the _id property to the fruit schema and because _id is a required property of all MongoDB document, mongoose would help you auto-generate a new _id when it creates the query to send to the database. The _id it generates when you run watermelon.save() is different from the _id it generates when you run person.save(), this is why you are seeing the two different _ids.
The fix:
What you need to do is add the _id property to the fruit schema(and maybe the person schema to avoid further surprises) and then explicitly generate an _id your self before saving the document into the database.
The fruit schema should be like this after adding the _id property:
const fruitSchema = new mongoose.Schema({
_id: mongoose.ObjectId,
name: {
type: String,
required: true
},
rating: {
type: Number,
min: 1,
max: 10,
},
review: String
});
And when instantiating the fruit model, add the _id value yourself:
const watermelon = new Fruit({
_id: mongoose.Types.ObjectId(), // this helps generate a unique objectId
name: "Watermelon",
rating: 7,
review: "Meh."
});

Create function to init model schema

Recently, at an interview, I was given a task that I could not solve. I would be very happy if someone helps to figure out how to solve it!
"Create a function to init model schema. Add method to define relation one-to-one, one-to-many. Model fields should have types. Raise an error when type is not corresponding."
const Card = Model({
number: Number,
pin: String
});
const Post = Model({
title: String,
description: String
});
const User = Model({
name: String,
age: Number,
posts: Model.hasMany(Post),
card: Model.hasOne(Card),
});
User.prototype.hasCard = function() {
return !!this.card;
};
const user = new User({
name: 'User',
age: 25,
posts: [{
title: 'Post1',
description: 'Post description'
}],
card: null
});
console.log(user.hasCard()); //false

Mongodb, storing comments to a specific post

My userSchema looks something like this:
var UserSchema = new Schema({
name: { type: ......},
email: { type..... },
test1: {
[
[0] { test: Array },
[1] { test: Array }
]
}
)};
With a few other objects not included here. In the object that's in test1 there is stored some data to which i want to add or somehow bind an array of comments. The problem is that I'm not sure which is the best way to implement this? If i should create a new commentSchema and somehow connect the comments with the object or how to do it. Can anyone give me some tips on how to implement it?
You can create your schema as follows:
var CommentSchema = new Schema({
user: {type: Schema.Types.ObjectId, ref: 'User', required: true},
message: String,
});
var UserSchema = new Schema({
name: { type: ......},
email: { type..... },
...
test1: {
comments: [CommentSchema]
}
... OR
comments: [CommentSchema]
)};
or if you are trying to do something like posts with comments try
var PostSchema = new Schema({
comments: [CommentSchema]
postBody: String
})
var UserSchema = new Schema({
name: { type: ......},
email: { type..... },
...
posts: [PostSchema]
...
)};

Mongoose: Schema for nested Json and store it (Node.js)

I'm pretty new to js and mongoose and I've ended up with a nested JSON.
var standardmessage = {
"id": "352",
"name": "a name",
"type": "a type",
"message":
{
"messagetype": "default message",
"timestamp": "35235326326",
"messagestatus": "running"
}
}
Now I tried to define a schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var messageSchema = new Schema({
id: Number,
name: Schema.Types.Mixed,
type: Schema.Types.Mixed,
message:
{
messagetype: String,
timestamp: Number,
messagestatus: String
}
}, {collection: 'test'});
var testmodel = mongoose.model('messagemodel', messageSchema,'test');
module.exports = testmodel;
Finally I tried to store it through Mongoose into MongoDB:
var Message = new testmodel({standardmessage});
Message.save(function (err) {
if (err) console.log(err);
});
Either my schema is wrong and i need multiple schemas to store it correctly or sth. else is wrong. But in my database it only get's stored like this:
{ "_id" : ObjectID("xxxxxxxxxxx"), "__v" : 0}
Is it possible to define one Schema to store this nested JSON? If yes, how?
If not, how do I manage to store it correctly?
Why does it only store an ObjectID?
Thanks in advance, appreciating every kind of help and sorry if my question is stupid as im new to this.
Update:
var messageSchema = new Schema({
id: Number,
name: Schema.Types.Mixed,
type: Schema.Types.Mixed,
message: [message]
}, {collection: 'test'});
var message = new Schema({
"messagetype": "default message",
"timestamp": "35235326326",
"messagestatus": "running"
})
Then it gets stored like this { "_id" : ObjectID("xxxxxxxxxxx"), "message" : [], "__v" : 0}
For a nested JSON, you can do something like this:
var mongoose =require('mongoose');
var Schema = mongoose.Schema;
var standardmessage = new Schema({
id: Number,
name: String,
type: String,
message: {
messageType: String,
timestamp: Number,
messagestatus: String
}
});
If the nested block is a list then you can do this:
var mongoose =require('mongoose');
var Schema = mongoose.Schema;
var msg = new Schema({
messageType: String,
timestamp: Number,
messagestatus: String
});
var standardmessage = new Schema({
id: Number,
name: String,
type: String,
message: [msg]
});

How to create field using variable name?

How can I create a field in mongoose using a variable name? I've seen some ways to do it using .update(), but I was wondering if there was a way to do it when creating a new document
I have my schema like:
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
})
and my object:
var date = '2015-02-01'
var obj = {
ios: 100,
android: 500
}
var doc = {}
doc[date] = obj
var mongoDoc = new Summaries({
name: 'John',
type: 'person',
date: date,
$doc: doc
})
mongoDoc.save(function(err){
if(!err) log('done')
else log(err.toString())
})
But it only saves the fields 'name', 'type' and 'date'.
Can anyone tell me if its possible to do something like that and if so, what am I missing?
Got it..
first part from #Alex is right, just change the schema strict property to false so I can add new fields to my mongo document. For the field name as a variable, I just first created my entire object and then create a new instance of the document:
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
}, { strict: false })
var date = '2015-02-01'
var obj = {
name: 'John',
type: 'person',
date: date
}
obj[date] = {
ios: 100,
android: 500
}
var mongoDoc = new Summaries(obj)
mongoDoc.save(function(err){
if(!err) log('Done.')
else log(err)
}
Success!
EDIT
Three years later ES6 syntax also allows us to do so:
var mongoDoc = await new Summaries({
name: 'John',
type: 'person',
date: date,
[date]: { ios: 100, android: 100 }
}).save();
Change your schema definition to
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
}, { strict: false })

Categories