I am trying to save a leader board made of objects nested in an array. I want to save it in my database, but I have not been able to create the right schema and I don't think I that is the best way to go.
When I run the code I get the error of:
"LeaderBoardSchema is not a constructor".
What is the appropriate way of creating a schema that I need.
I have tried many variations looking online, but I keep getting the " LeaderBoardSchema is not a constructor".
The examples from other questions on S.O have not been able to help me much.
// leaderboard object that i want to save
leaderBoard = [
leaderOne= {
name: 'Ultimate Beast',
score: 2
},
leaderTwo= {
name: 'Masked Titan',
score: 9
},
leaderThree= {
name: 'Oranolio',
score: 7
},
leaderFour= {
name: 'Popularkiya',
score:1
},
leaderFive= {
name: 'Bootecia',
score: 11
},
];
// Database schema
const Schema = mongoose.Schema()
const LeaderBoardSchema = new mongoose.Schema({
leaderBoard:{
leaderOne : {
name: String,
score: Number
},
leaderTwo : {
name: String,
score: Number
},
leaderThree : {
name: String,
score: Number
},
leaderFour : {
name: String,
score:Number
},
leaderFive : {
name: String,
score: Number
}
}
}, {collection: 'leaderboard-data'});
const PlayerData = mongoose.model('LeaderBoard Data', LeaderBoardSchema);
// My attempt
const leaderBoardToSave = new LeaderBoardSchema({
leaderBoard:{
leaderOne : {
name: 'asdf',
score: 12
},
leaderTwo : {
name: 'sfgh',
score: 12
},
leaderThree : {
name: 'weh',
score: 12
},
leaderFour : {
name: 'asdf',
score:12
},
leaderFive : {
name: 'asdf',
score: 12
}
}
})
Currently your leaderBoard field is an object. To model an array of objects do the following with your schema:
const LeaderBoardSchema = new mongoose.Schema({
leaderBoard: [
{
name: String,
score: Number
}
]
}, {collection: 'leaderboard-data'});
as for the issue with the schema constructor. You're creating the mongoose model as follows const PlayerData = mongoose.model('LeaderBoard Data', LeaderBoardSchema);. But then you do new LeaderBoardSchema({...}). You need to use the mongoose model PlayerData instead. so to create a new leaderboard:
const leaderBoardToSave = new PlayerData({
leaderBoard: [
{
name: 'asdf',
score: 12
},
{
name: 'gds',
score: 12
},
{
name: 'adad',
score: 12
},
]
})
Related
I'm working on a project and currently using Mongodb Time-Series and aggregation.
I connected my Apollo Graphql to retrieve the data but i'm stuck with an error that i can not solve no matter what.
Float cannot represent non numeric value:
On my db the numbers are saved as Double. If i try to run the query in MongoDB Aggregation with MongoDBCompass it's working perfectly but not on my Nodejs database.
I tried googling my problem first and looking ad docs but all the different solution i found do not solve my problem, any suggestions?
This is my Query:
module.exports = async (root, { limit }, { models }) => {
const keyx = await models.Weather.aggregate([
{
$group: {
_id: {
yearMonthDay: {
$dateToString: { format: "%Y-%m-%d", date: "$timestamp" },
},
},
temp: {
$push: { temp: "$temp" },
},
},
},
])
.exec();
return keyx;
};
This is my model:
const mongoose = require("mongoose");
const { Schema } = mongoose;
mongoose.pluralize(null);
const weather = new Schema({
timestamp: {
type: String,
trim: true,
},
temp: {
type: Number,
trim: true,
},
});
const Weather = mongoose.model("time_weather", weather);
module.exports = { Weather };
and this is my types:
const { gql } = require("apollo-server");
module.exports = gql`
type Weather {
timestamp: String
_id: ID
temp: Float
}
type Query {
weather(limit: Int): [Weather]
}
`;
and finally this is the response i'm getting from apollo studio:
{
"errors": [
{
"message": "Float cannot represent non numeric value: [{ temp: 11.7 }, { temp: 11.7 }, { temp: 12.01 }, { temp: 13.21 }, { temp: 13.21 }, { temp: 11.93 }, { temp: 13.21 }, { temp: 12.73 }, { temp: 14.21 }, { temp: 11.7 }, ... 14 more items]",
"locations": [
{
"line": 6,
"column": 5
}
],
"path": [
"weather",
0,
"temp"
],
}
},
I have the following schema:
const mySchema = new mongoose.Schema({
name: String,
subscribers: [ { name: String } ]
})
const myModel = mongoose.model('User', mySchema, 'users')
and I have this code in one of my controllers:
const allOfHisSubscribers = await myModel.findById(req.params.id).select('subscribers')
I want the database response of the await myModel.findByid call to be:
[
{ name: 'x' },
{ name: 'y' },
{ name: 'z' },
]
However, the code above is returning:
{
subscribers: [
{ name: 'x' },
{ name: 'y' },
{ name: 'z' },
]
}
I don't want the JavaScript way of doing it, I know you can use something like Array.prototype.map to get the result, but I am using a middleware, so I can only use the mongoose or MongoDB way of doing it (if possible).
Got it :D, if not, let me know in the comments 🌹
This is the model:
Schema = mongoose.Schema;
module.exports = mongoose.model(
"Leveling",
new Schema({
guildID: {
type: String
},
guildName: {
type: String
},
roletoad: {
type: String,
default: "null"
},
roletoremove: {
type: String,
default: "null"
},
rolelevel: {
type: Number,
default: 0
},
})
);
This is the command to get all leveling roles in a specific guild:
if(args[0]==="list"){
const del = await Leveling.find({
guildID: message.guild.id,
},{
_id: 0,
roletoad: 1,
roletoremove: 1,
rolelevel:1
})
return await message.channel.send(del)
}
This is the output:
{
roletoad: '735106092308103278',
roletoremove: '731561814407774248',
rolelevel: 5
}
{
roletoad: '735598034385371167',
roletoremove: '744562691817078905',
rolelevel: 7
}
I want to know how to get each item(roletoad,roletoremove,rolelevel) in a specific variable.
It seems you're getting an array of objects form your db in the del variable, and each object in that array has the properties roletoad, roletoremove and rolelevel, which you want in separate variables.
For each object of your array, you can store these properties in variables by object destructuring. One approach is as follows:
//the data you'll get from the db
const del = [{
roletoad: '735106092308103278',
roletoremove: '731561814407774248',
rolelevel: 5
},
{
roletoad: '735598034385371167',
roletoremove: '744562691817078905',
rolelevel: 7
}]
for(const {
roletoad: yourRoleToAddVar,
roletoremove: yourRoleToRemoveVar,
rolelevel: yourRoleToLevelVar
} of del){
console.log(`Role to add: ${yourRoleToAddVar}`)
console.log(`Role to remove: ${yourRoleToRemoveVar}`)
console.log(`Role Level: ${yourRoleToLevelVar}`)
console.log(`---------------------------`)
//do what you want with these variables here
}
NOTE: This should go without saying but the scope of these variables will only be valid within this loop.
I am facing some issues while inserting data into nested documents structure of mongoDb.
Following is the Mongoose Model:
const funnel = new mongoose.Schema({
funnelName:{
type:String,
unique:true
},
group: String,
category: String,
funnelStep: {
stepType: String,
stepName: String,
stepPath: String,
isTracking: Boolean,
viewsStorage: []
} })
Below is the push I am sending to Db:
router.post('/createFunnel',async (req,res)=>{
if(!req.body.funnelName || !req.body.group || !req.body.category)
{return res.status(422).json({error:"Please add all the fields."})}
try{
const funnelSteps = []
funnelSteps.push({
stepType: req.body.stepType,
stepName: req.body.stepName,
stepPath: req.body.stepPath,
isTracking: req.body.isTracking,
viewsStorage: req.body.viewsStorage
})
const funnels = new Funnel({
funnelName : req.body.funnelName,
group : req.body.group,
category : req.body.category,
funnelStep : funnelSteps
})
await funnels.save(function(err){
if(err){
return res.status(422).send({error: err.message})
}
return res.json(funnels)
})
} catch(err){
return res.status(422).send({error: err.message})
} })
Below is the data structure I am sending through postman:
{
"funnelName":"Name-Funnel",
"group":"AVC",
"category":"XYZ",
"funnelStep":[
{
"stepType":"Advert",
"stepName":"Angle",
"stepPath":"google.com",
"isTracking":1,
"viewsStorage":[0,0]
},
{
"stepType":"Optin",
"stepName":"Ver 1",
"stepPath":"fb.com",
"isTracking":1,
"viewsStorage":[1,0]
},
{
"stepType":"Check",
"stepName":"rev-cat",
"stepPath":"google.com",
"isTracking":0,
"viewsStorage":[2,0]
}
] }
Below is the output I am getting in response:
{
"funnelStep": {
"viewsStorage": []
},
"_id": "5ec0ff78a6dfab18f4210e96",
"funnelName": "Testing The Latest Method4",
"group": "AVC",
"category": "XYZ",
"__v": 0
}
How can I fix this issue as my data is not getting inserted properly?
And apart from this, in the viewsStorage array, how to store date and a number which will increment after a certain operations and will get saved in the array according to the dates?
I think there is an issue in the funnelSteps array creation part. You are trying to get data directly from req.body instead of req.body.funnelStep
const funnelSteps = []
req.body.funnelStep.forEach(fs => {
funnelSteps.push({
stepType: fs.stepType,
stepName: fs.stepName,
stepPath: fs.stepPath,
isTracking: fs.isTracking,
viewsStorage: fs.viewsStorage
})
})
Schema
const funnel = new mongoose.Schema({
funnelName:{
type:String,
unique:true
},
group: String,
category: String,
funnelStep: [{
stepType: String,
stepName: String,
stepPath: String,
isTracking: Boolean,
viewsStorage: []
}] })
I have been trying to use updatemany with mongoose. I want to update the values in database using an array of objects.
[
{
"variantId": "5e1760fbdfaf28038242d676",
"quantity": 5
},
{
"variantId": "5e17e67b73a34d53160c7252",
"quantity": 13
}
]
I want to use variantId as filter.
Model schema is:
let variantSchema = new mongoose.Schema({
variantName: String,
stocks: {
type: Number,
min: 0
},
regularPrice: {
type: Number,
required: true
},
salePrice: {
type: Number,
required: true
}
})
I want to filter the models using variantId and then decrease the stocks.
As you need to update multiple documents with multiple criteria then .updateMany() wouldn't work - it will work only if you need to update multiple documents with same value, Try this below query which will help you to get it done in one DB call :
const Mongoose = require("mongoose");
let variantSchema = new mongoose.Schema({
variantName: String,
stocks: {
type: Number,
min: 0
},
regularPrice: {
type: Number,
required: true
},
salePrice: {
type: Number,
required: true
}
})
const Variant = mongoose.model('variant', variantSchema, 'variant');
let input = [
{
"variantId": "5e1760fbdfaf28038242d676",
"quantity": 5
},
{
"variantId": "5e17e67b73a34d53160c7252",
"quantity": 13
}
]
let bulkArr = [];
for (const i of input) {
bulkArr.push({
updateOne: {
"filter": { "_id": Mongoose.Types.ObjectId(i.variantId) },
"update": { $inc: { "stocks": - i.quantity } }
}
})
}
Variant.bulkWrite(bulkArr)
Ref : MongoDB-bulkWrite
I don't think this can be done with a single Model.updateMany query. You will need to loop the array and use Model.update instead.
for (const { variantId, quantity } of objects) {
Model.update({ _id: variantId }, { $inc: { stocks: -quantity } });
}
To run this in a transaction (https://mongoosejs.com/docs/transactions.html), the code should look something like this (however I have not tried or tested this):
mongoose.startSession().then(async session => {
session.startTransaction();
for (const { variantId, quantity } of objects) {
await Model.update({ _id: variantId }, { $inc: { stocks: -quantity } }, { session });
}
await session.commitTransaction();
});