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
})
]
})
Related
I have a collection called Orders that contains this schema:
const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
restaurant: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Restaurant',
required: true
},
dishes: [
{
dish: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Dish'
},
amount: Number
}
],
price: {
type: Number,
required: true
},
comment: {
type: String,
required: false
},
status: {
type: String,
enum: ['PROCESSING', 'CANCELLED', 'COMPLETED', 'ERROR'],
default: 'PROCESSING'
},
timestamp: {
type: Date,
default: Date.now
}
})
module.exports = mongoose.model('Order', orderSchema);
Inside my router, I have this code:
let orders = await Order.find({restaurant: restaurantID, status:'PROCESSING'}).populate('dishes._id').exec()
Order.find does not throw an exception, but it isnt working either.
I want the res.body to look like this:
{
"_id": "objectID",
"user": "objectID",
"restaurant": "objectID",
"dishes": [
{
"amount": number,
"dish": {
//dish object
}
},
...
],
//other order properties
},
...
]
But for some reason the dishes array looks like this:
"dishes": [
{
"amount": 1,
"_id": "6184e848e6d1974a0569783d"
}
],
What am I doing wrong?
I know that if populate() worked the res.body dishes array would not have a property called 'dish' and instead have a property called _id that would contain the dish object, but this shouldnt be hard to change once populate() works.
EDIT:
I realised that my createOrder route could be part of the problem since it ignores my schema and uses an id property for the objectID instead of dish. The array I save to the DB contains a property called id for the id instead of dish, but shouldnt my schema throw an exception when i try to save something like this to my database?
At first glance, I think the problem might be that you have a syntax problem.
Try
.populate('dishes').exec()
instead of
.populate('dishes._id').exec()
Here is my problem I have two schemas one nested in another as an array. I am trying to push into the array and save the subdocument but it is not saving properly, I get an object that is saved but none of the fields are saved except for its _id. Do I have to save each model individually first? What is the issue here?
Here are my two schemas:
import mongoose from "mongoose";
import {contactSchema} from "./ContactSchema"
export const bigSchema = new mongoose.Schema({
testField: {
type: String,
required: true,
},
contacts: [{ contactSchema }],
}
});
export default mongoose.model("Big", bigSchema);
import mongoose from "mongoose";
export const contactSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
age: {
type: number,
required: false,
}
});
export default mongoose.model("Contact", contactSchema);
Here is my code that I use to push to the array of contacts.
public async saveContact(
testField: string,
name: string,
age: number,
) {
const newContact = new Contact({
name: name,
age: age,
});
console.log(newContact);
return UserContacts.findOneAndUpdate(
{
testField: testField,
},
{ $push: { contacts: newContact } },
{ new: true, upsert: true }
);
}
However when I check my database, this is what I see instead. There is an objectId but not what I expect to see, which is a list of Contact subdocuments inside my "Big" document
{
"_id" : ObjectId("XXXX"),
"testField" : "XXXXX",
"contacts" : [
{
"_id" : ObjectId("XXXXX")
}
],
"__v" : 0
}
export const bigSchema = new mongoose.Schema({
testField: {
type: String,
required: true,
},
contacts: [{ contactSchema }],
}
});
should be:
export const bigSchema = new mongoose.Schema({
testField: {
type: String,
required: true,
},
contacts: [contactSchema],
}
});
Try that and see what happens.
Edit: Also, if you intend for contacts to be an array of references to the Contact model, then you need to do this instead:
export const bigSchema = new mongoose.Schema({
testField: {
type: String,
required: true,
},
contacts: [{type: mongoose.Schema.Types.ObjectId, ref: 'Contact'}],
}
});}
This will make contacts an array of Contact IDs, so you're not duplicating any data, but just referencing the contacts in their collection. docs
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 });
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.
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]
});