This Code is fetching JSON data from an API service correctly but not updating a nested document in MongoDB, Almost tried everthing
api.squad(matchid, function(datapack) {
var data = JSON.parse(datapack);
for (var i = 0; i < data.squad.length; i++) {
players = data.squad[i].players;
for(var j = 0; j < players.length; j++){
console.log(players[j]); // Working Fine Till here , Data from api showing here in console
var player = { pid: players[j].pid, name: players[j].name };
squadModel.update(
{ leagueId: leagueId },
{$push: {players: player} } // This Update is Not Working
);
}
}
});
The Schema Is As Follows for the code.
// Squad Players -- Sub Schema of Squad
var squadPlayersSchema = mongoose.Schema({
pid:{
type: Number,
required: true
},
name:{
type: String,
required: true
},
type:{
type: String,
},
cost:{
type: Number,
},
country:{
type: String,
},
status : {
type:Boolean,
default:false
}
});
// Squad Schema
var squadSchema = mongoose.Schema({
leagueId:{
type: mongoose.Schema.Types.ObjectId,
ref :'leagueModel',
required: true
},
players : [squadPlayersSchema],
isLaunched : {
type:Boolean,
default:false
}
});
var squads = module.exports = mongoose.model('squads', squadSchema);
Pls help this thing has just refused to work. The update query is just working fine in MongoDB GUI Studio3T Shell
Example Of a demo query run in Studio3T and works fine and updates the document with the code above doesn't.
db.squads.update(
{ "leagueId": ObjectId("5a85900d8b3b30165875ff0d") },
{
"$push": {
"players": { pid: 1234567, name: "Some Name" }
}
}
);
Use $each with $addToSet as follows:
api.squad(leagueId, datapack => {
const data = JSON.parse(datapack);
let updates = []; // array to hold updates promises
data.squad.forEach(squad => { // iterate the data.squad array to get the players list
let promise = squadModel.findOneAndUpdate(
{ leagueId: leagueId },
{ '$addToSet': { 'players': { '$each': squad.players } } },
{ 'upsert': true }
); // update operation as a promise
updates.push(promise);
});
Promise.all(updates).then(console.log).catch(console.error); // resolves when all of the updates promises have resolved
});
Related
MongoDb documents looks like this:
{
"_id": {
"$oid": "60abf5ffc4b1cb61e05bdc48"
},
"club": "FC Midtjylland",
"number": 6,
"__v": 0,
"name": "Joel Andersson"
}
If I create a filter in MongoDB Compass like:
{number: { $in: [6,11] } }
I get all documents with number 6 and 11
In mongose my schema is like:
const Player = new Schema ({
club: { type: String, required: true },
name: { type: String, required: true },
number: { type: Number, required: true },
image: { type: String, required: false },}, { collection: 'players' });
If I try to find the same documents in node.js with mongoose i get no results:
var test = "6,11"
Player.find({number: { $in: [test] }}, function (err, player) {
if (!player || player.length <= 0) {
console.log('No player found!')
ws.send('No player found!');
}
else {
//ws.send(player.number+','+player.name+','+player.image);
console.log(player)
}
})
If I input the numbers directly in the query everything is working fine like:
Player.find({number: { $in: [6,11] }}, funct
What can I do to solve this?
try this:
var test = [6,11]
Player.find({number: { $in: test }}, function (err, player) {
if (!player || player.length <= 0) {
console.log('No player found!')
ws.send('No player found!');
}
else {
//ws.send(player.number+','+player.name+','+player.image);
console.log(player)
}
})
i have the following schema type:
Paitnet:
var PaitentSchema = new mongoose.Schema({
username: String,
password: String,
name: String,
protocol: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Protocol'
},
treatmentTypes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'TreatmentType'
}],
accesses: [AccessSchema],
reports: [ReportSchema],
}, { collection: ' Paitents' });
and the AccessSchema:
var AccessSchema = new mongoose.Schema({
stageBool: Boolean,
exerciseBool: [{ type: Boolean }]
});
and what I'm trying to do is to update the exerciseBool array for example change one of the values in the array from 'false' to 'true'.
I have tried this code and its work for me but the Problem is that I get the index from the client so I need to embed the indexes in dynamically way (not always 0 and 1)
here is what I did(not dynamically ):
const paitent = await Paitent.updateOne({ username: req.params.username },
{ $set: { "accesses.0.exerciseBool.1": true } });
I want to do something like this but in dynamically indexes way.
please someone can help me?
thanks.
As you said, indexes are known but values may change.
you can use the following to create your query.
const accessesIndex = 0;
const exerciseBoolIndex = 1;
const update = { $set: { [`accesses.${accessesIndex}.exerciseBool.${exerciseBoolIndex}`]: true } };
console.log(update);
//const paitent = await Paitent.updateOne({ username: req.params.username }, update); // run your update query like this
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Update
Check the index exists or not then only update the record.
add into your query "accesses.0.exerciseBool.1": { $exists: true } to make sure the accesses.0.exerciseBool.1 exists in the record.
const accessesIndex = 0;
const exerciseBoolIndex = 1;
const username = 'abc';
const key = `accesses.${accessesIndex}.exerciseBool.${exerciseBoolIndex}`;
const query = { username, [key]: { "$exists": true } };
console.log('query:', query);
const update = { $set: { [key]: true } };
console.log('update:', update);
Update Working demo - https://mongoplayground.net/p/GNOuZr3wqqw
No update demo - https://mongoplayground.net/p/nsTC8s-ruyo
If you are using MongoDB version >= 4.4. you can use $function along with update-with-aggregation-pipeline to update array dynamically. Try this:
let index1 = 0;
let index2 = 1;
db.patients.updateOne(
{ username: "dhee" },
[
{
$set: {
accesses: {
$function: {
body: function(accesses, index1, index2) {
if (accesses[index1] != null
&& accesses[index1].exerciseBool[index2] != null) {
accesses[index1].exerciseBool[index2] = true;
}
return accesses;
},
args: ["$accesses", index1, index2],
lang: "js"
}
}
}
}
]
);
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'm actually trying to convert mongodb references into those references' documents value (info.value) using mongoose in javascript.
Tried that by using map, for/forEach, and nothing did the job since mongoose requests are async.
Not really used to this kind of code, I feel a bit lost after all those things I tried.
Maybe someone would like to give me a hint about this by taking a look at the code below.
Just for information, no need to worry about loading templates, connecting to mongo, ... since everything else is working just fine.
That's the closest I got to the expected result, but still, it throws me errors when I try to "console.log(cond[c]);/console.log(info);" (cond[c] and info are null and undefined)
Well this function also needs to be prepared to be recursive since I plan to put sub-blocks in the "content" property of the bloc objects.
Thanks a lot for your time guys.
// Input condition
"H1Vf3KTef || false"
// Expected result
"1 || false"
// Buggy Function
var execIfBlock = function recursExec (query, callback) {
IfBlockModel.findOne(query, function(err, ifBlock) {
if (!err) {
var cond = ifBlock.condition.split(" ");
//console.log('Block : ' + ifBlock);
//console.log('Condition : ' + cond);
var calls = new Array();
for (var c = 0, len = cond.length; c < len; c++) {
if (shortId.isValid(cond[c])) {
calls.push(function() {
InfoModel.findOne({ _id: cond[c] }, function(err, info) {
console.log(cond[c]);
console.log(info);
cond[c] = info.value;
});
});
}
}
async.parallel(calls, function(err, result) {
console.log(result);
// Do some job using the final expected result : "1 || false"
});
}
});
};
// Info template
{
"_id": "H1Vf3KTef",
"value": "1"
}
// Bloc template
{
"_id": "rkRBtLTef",
"content": [],
"condition": "H1Vf3KTef || false"
}
// Info schema
var InfoSchema = new Schema({
_id: { type: String, unique: true, required: true, default: shortId.generate },
value: { type: String, default: "0" }
});
// Bloc schema
var IfBlockSchema = new Schema({
_id: { type: String, unique: true, required: true, default: shortId.generate },
condition: { type: String, required: true, default: true },
content: [{ type: String, required: true, default: '', ref: 'block' }]
});
Use promises and break your code in small functions :
var execIfBlock = function recursExec(query, callback) {
IfBlockModel.findOne(query, function (err, ifBlock) {
if (!err) {
var cond = ifBlock.condition.split(" ");
updateMultipeInfo(cond)
.then(values => {
console.log(values) // [values1, values ,...]
});
}
});
};
function updateMultipeInfo(cond){
return Promise.all(cond.map(updateInfo))
}
function updateInfo(id){
if (shortId.isValid(id)) {
return InfoModel
.findOne({ _id: id })
.then(info => info.value);
} else {
return Promise.reject("invalid id");
}
}