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

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]
});

Related

Mongoose Shema for Json Object

I am trying to create a mongoose schema for a json object which i will recieve from an api.
The json object has an element payMoneyid which is like this
payuMoneyId: {
"paymentId": 1112253696,
"splitIdMap": [{
"amount": 10.00,
"splitPaymentId": 1112253697,
"merchantId": 4825051,
"splitId": "splitId1"
}]
}
I have written a schema is this how it's supposed to be or it's wrong?
const formSchema = new mongoose.Schema({
payuMoneyId: {
paymentId: {
type: Number
},
splitIdMap: {
type: Mixed
}
}
})
It looks like you have just two top level fields - a number and an array of objects. Here is how to mirror that structure in a mongoose schema:
const formSchema = new mongoose.Schema({
paymentId: Number,
splitIdMap: [
new mongoose.Schema({
amount: Number,
splitPaymentId: Number,
merchantId: Number,
splitId: String
})
]
})

Why mongoose populate doesn't work when populating an array?

I have 2 schemas:
const mongoose = require('mongoose');
const PinSchema = new mongoose.Schema({
title: String,
content: String,
image: String,
latitude: Number,
longitude: Number,
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
},
comments: [
{
text: String,
createdAt: {
type: Date,
default: Date.now,
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
}
}
}
]
}, { timestamps: true });
module.exports = mongoose.model("Pin", PinSchema);
and
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: String,
email: String,
picture: String
});
module.exports = mongoose.model("User", UserSchema);
As you can see author field in Pin is the same as the _id in User schema.
I then try to populate the comments author field in the Pin schema like this:
const pinUpdated = await Pin.findOneAndUpdate(
{ _id: pinId },
{ $push: { comments: "some comment" } },
{ new: true }
).populate("author")
.populate("comments.author");
however the result object has author field set to null so population doesn't work.
I'm not against doing this with native mongo syntax using $lookup but in my case it's not just looking up an array it's looking up a field of an objects array:
db.pins.aggregate([
{
$lookup:
{
from: "users",
localField: "comments._id", // this won't work
foreignField: "_id",
as: "authorOutput"
}
}
])
what am I missing in populate()?
It looks like your author field in the comments array is nested inside the createdAt object, which is likely unintentional. Changing PinSchema to the following (closing curly brace before author) should fix it:
const PinSchema = new mongoose.Schema({
...
comments: [
{
text: String,
createdAt: {
type: Date,
default: Date.now,
},
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
}
}
]
}, { timestamps: true });

MongoDB: Populate or Query for two collections

I have the following Schemas:
let ProjectSchema = new mongoose.Schema({
title: {
type: String
},
employees: {
user: String, // ==> ObjectId of User from UserSchema
role: String,
workload: Number,
},
description: {
type: String
}
});
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true
},
name: {
type: String
},
projects: {
type: Array // ==> ObjectId of Project from ProjectSchema
}
});
What I want to achieve is to get the user by _id or email and to get also all data from his projects like:
{
"user": {
"_id": "asdf1234",
"email": "your#email.com",
"name": "Max"
"projects": {
"title": "Project 1",
"description": "Just a text",
"employees": {
"user": "asdf1234",
"role": "developer",
"workload": 40
}
}
}
}
And I also want to get a specific project by Id and the employee.user field should be populated with the correct user data.
Can I do this with Mongoose populate?
My approach would be to first do a User.findOne() and then check the project.id and to a Project.findOne().
how about in your UserSchema you reference an array of projects, that way when you query for the user you are querying for all the projects tied to the user.
let mongoose = require("mongoose");
let Projects = require("./projects");
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true
},
name: {
type: String
},
projects: {
type: [Projects.schema]
}
});
Then every time you query for the user it comes with the projects associated to the user.

Mongoose - save object with objectid

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();
});

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]
...
)};

Categories