Create new model instance with array inside - node.js

I have the following model settings:
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
areas: [{
area: {
type: Number,
required: true,
enum: [0, 1, 2, 3, 4, 5],
}
}],
}, {
timestamps: true
});
const Item = mongoose.model('Item', itemSchema);
module.exports = Item;
When I try to save an instance in the DB:
const item = new Item({
areas: [1, 2, 3],
});
item.save();
I get the following error:
Item validation failed: areas: Cast to embedded failed for value "1" at path "areas"
CastError: Cast to embedded failed for value "1" at path "areas"
Why do I get this error? I can't find what Schema rule I broke..

I think its because you are setting the areas as an array of objects that contains area property, like:
[{area: 1}, {area: 2}, {area: 3}]
Maybe you could try set it as:
areas: [{
type: Number,
required: true,
enum: [0, 1, 2, 3, 4, 5],
}],

Related

Get average rate for product comments in MongoDB and Express

I want to calculate average rating for products based on comments rate,
exactly I want to return products object with one more property in response when client call get all product api
my product schema is like below, thank you in advance.
const mongoose = require("mongoose");
const { s, rs, n, rn, ref, rref } = require("../utils/mongo");
let commentSchema = new mongoose.Schema(
{
user: rref("user"),
body: rs,
rate: {
...n,
default: 0,
enum: [0, 1, 2, 3, 4, 5],
},
},
{ timestamps: true }
);
let schema = new mongoose.Schema(
{
user: rref("user"),
name: rs,
description: s,
images: [s],
price: rn,
discount: n,
sizes: [sizeSchema],
categories: [ref("category")],
tags: [s],
comments: [commentSchema],
rating: n,
inStock: {
type: Boolean,
default: true,
},
stock: n,
sold: {
...n,
default: 0,
},
view: {
...n,
default: 0,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("product", schema);
I want to return in response something like this:
let result = [
{
name: 'product name',
comments: [
{
user: "2a2sdw22das5262123223",
body: "good product",
rate: 4
},
{
user: "2a2sdw22das5262123223",
body: "good product",
rate: 2
}
],
avgRate: 2, // how to calculate this?
price: 20
...
}
]
You can use aggregation pipeline to do that, it will add the avgRating field avgRate which you can use for future ref:
db.collectionName.aggregate([{ $addFields : { avgRate: { $avg: "$comments.rate"} } }])

Mongoose is saving only objectId instead of the whole object

I am trying to save array of objects, but it is just saving the ObjectIds instead of whole objects, even thought in schema there is no refference or something like that.
So, I have this schema:
let MatchPlayerSchema = new Schema({
deck: {type: Array, default: []}
});
And I am trying to save this array tooken from database (playerDeck):
[ { _id: 5a1fc7ee667b103aace5f3ec,
magicResist: 10,
armor: 10,
attack: 10,
health: 10,
name: 'Test',
__v: 0,
type: 'CardUnit' },
{ _id: 5a1fc7ee667b103aace5f3ec,
magicResist: 10,
armor: 10,
attack: 10,
health: 10,
name: 'Test',
__v: 0,
type: 'CardUnit' }]
Like this:
let player = new MatchPlayer();
player.deck = playerDeck;
player.save();
However, the result is:
"deck" : [
ObjectId("5a1fc7ee667b103aace5f3ec"),
ObjectId("5a1fc7ee667b103aace5f3ec")
]
I have tried to set deck to: [Schema.Types.Mixed], but it didnt not help either.
When I try to save something just like: ['test', 'test'], it saves alright.
I just can not figure out, what am I doing wrong.
Any ideas? Thank you
I had the same issue and setting the
mongoose.set('debug', true);
helped me to see what mongoose actually sending to the DB.
I was having in the Schema
const ChatSchema = mongoose.Schema({
messages: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Message',
}],
isRemoved: {
type: Boolean,
default: false,
required: true
}
});
After switching the type to mongoose.Schema.Types.Mixed it worked perfectly. This is how I was invoking an update
Chat.findOneAndUpdate({ _id: req.params.chatId }, { $push: { messages: message }},{new: true});
let MatchPlayerSchema = new Schema({
deck: {
type: Schema.Types.Mixed
}
});
You should be able to store an array of objects into 'deck'

How to update an element of an array of strings on Mongoose?

I'm trying to update an element of an array inside my model. It's a simple array of Strings. When I run the code, the element is updated, but it's inserting a new array with the value 'newType'. I'm using mongoose 4.11.7.
The result I expect is:
['a', 'b', 'newType'] but after the update it's returning ['a', 'b', ['newType']].
const profile = await Profile.findOneAndUpdate({
_id: 1,
types: 'oldType'
}, {
$set: {
'types.$': 'newType'
}
});
My Model is:
const schema = new Schema({
types: [{
type: String,
trim: true
}]
}, {
timestamps: true,
collection: 'Profile'
});

Mongoose self nesting

I'd like to store the following:
var TestSchema = new Schema({
name: {
type: String
},
regions: [RegionSchema]
}
var RegionSchema = new Schema({
name: {
type: String
},
minX: {
type: Number
},
minY: {
type: Number
},
minZ: {
type: Number
},
maxX: {
type: Number
},
maxY: {
type: Number
},
maxZ: {
type: Number
},
children: [this]
});
So as you can see I'm trying to make a region object, able to contain region objects, however this fails to save without exception, presumably the [this] in the schema gets stuck in some endless loop or something.
How can I make this to work for nesting regions?
The json payload I could expect to send to this schema:
name: "test123",
regions: [
{
name: "TestRegion",
minX: 0,
minY: 0,
minZ: 0,
maxX: 100,
maxY: 255,
maxZ: 100,
children: [
{
name: "TestRegionChild",
minX: 3,
minY: 3,
minZ: 3,
maxX: 97,
maxY: 252,
maxZ: 97,
children: []
}
]
}
]
I appreciate any help, thank you.
If your other regions are saved first, you can save the children as a list of objectIds like this:
children: [{
type: Schema.ObjectId,
ref: 'Region'
}]
Another option is to redesign your Schema and have a 'parent' on your Region and delete the 'children' field. Then when you need to get all the children you can query easily and not have big nested objects.
var RegionSchema = new Schema({
--- other fields omitted ---
parent: {
type: Schema.ObjectId,
ref: 'Region'
}
});

Default values in array mongoose

I am trying to make default values for array in mogoose schema:
warning:
type: Array
default: [10, 50, 99]
Am I right in such decision or there is some other way to do this?
Regarding to the Mongoose-Documentation, your way is correct.
Here a small example:
var arrayTestSchema = new Schema({
anArray: {
type: Array,
'default': [1, 2, 3]
}
});
And a link to the related documentation page: http://mongoosejs.com/docs/2.7.x/docs/defaults.html
for Mongoose v5.x
If you want to specify the type of the array child, you can define it like example below:
const BlogSchema = new Schema({
tags: {
type: [String],
default: ["tech", "economy"],
},
})
or
const BlogSchema = new Schema({
tags: {
type: [
{
type: String,
// Another properties
},
],
default: ["tech", "economy"],
},
})
References:
https://mongoosejs.com/docs/schematypes.html#arrays
It should be a json, I don't know what is what you posted there.
new Schema({
warning: { type: Array, default: [10, 50, 99] }
})

Resources