Issue with accessing the data I just created

I’m working with MongoDB and Javascript currently and ran into an issue I’m not sure how to go about.

First, here I check if a certain property exists and if not, I create it:

        if (!userdata.inventory[itemAdded.internalName]) {
        await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $set : { [`inventory.${itemAdded.internalName}`] : {} }
        }).then( async () => {
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $inc : { [`inventory.${itemAdded.internalName}.quantity`] : 0 }
            });
          })

    }

Afterwards, I’m trying to work with the property:

            if (!userdata.inventory[itemAdded.internalName][`1`]) {
            handledID = '1'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.1`] : {} }
            });
        } else if (!userdata.inventory[itemAdded.internalName][`2`]) {
            handledID = '2'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.2`] : {} }
            });
        } else if (!userdata.inventory[itemAdded.internalName][`3`]) {
            handledID = '3'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.3`] : {} }
            });

The issue is, this command only works from the second try. On every new user I run it on, it always fails at the first time, but works from the second one. For the first time userdata.inventory[itemAdded.internalName] returns undefined, even though if it didn’t exist I just created (and awaited) it a few lines above.

But if I run the command again on the same user (or on anyone who I am not running it on for the first time) it works flawlessly, it recognizes the data existing and is able to work with it. But the issue is that it should work for the first time too. I tried calling the second code block with a 30(!) second delay and it still returns undefined at the first try. Why am I not able to access the data I just created within the same command?

Hi @Lord_Wasabi,

Can you share a full code snippet.and the error?

I am not sure where is userdata intialized? Do you query it somehow?

I am not certain why in $set you have brackets on the left side? What are you trying to do push an empty object to a new array??

Thanks
Pavel

Thanks for your reply, of course it was not the whole code as it’s over 200 lines long and most of it is unrelated. However, I’ll try to post the full relevant code below:

const amountAdded = parseInt(args[1], 10)
const itemAdded = await client.db.itemdata.findOne({internalName: `${args[2]}`})
const userdata = await client.db.userdata.findOne({id: targetUser.id})

if (itemAdded.type === 'pet') {

let handledID = 0

    if (!userdata.inventory[itemAdded.internalName]) {
        await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $set : { [`inventory.${itemAdded.internalName}`] : {} }
        }).then( async () => {
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $inc : { [`inventory.${itemAdded.internalName}.quantity`] : 0 }
            });
          })

    }

        if (!userdata.inventory[itemAdded.internalName][`1`]) {
            handledID = '1'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.1`] : {} }
            });
        } else if (!userdata.inventory[itemAdded.internalName][`2`]) {
            handledID = '2'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.2`] : {} }
            });
        } else if (!userdata.inventory[itemAdded.internalName][`3`]) {
            handledID = '3'
            await client.db.userdata.updateOne({
                id: targetUser.id,
                }, {
                $set : { [`inventory.${args[2]}.3`] : {} }
            });
        } 


    if (handledID !== 0) {
        await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $set : { [`inventory.${args[2]}.${handledID}.rarity`] : args[3] }
        });

        await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $set : { [`inventory.${args[2]}.${handledID}.lvl`] : 1 }
        });

        await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $set : { [`inventory.${args[2]}.${handledID}.currentXP`] : 0 }
        });
    }      
}

Running it for the first time on a user results in this error:

(node:1364) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '1' of undefined
at Object.execute (C:\Users\wasab\Desktop\Csibebot\commands\dev\giveitem.js:90:60)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:1364) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

However, running it on them again works fine. I’d just like to make it work on the first try aswell.

Hi @Lord_Wasabi,

Your issue is on the java script side, since you cannot access members of non existing array. During your first run mongoDB returns nothing so you can’t access a member of undefined js object.

Instad of if (!userdata.inventory[itemAdded.internalName][1]) I think you should just ask if (!userdata)

There is no array elements in inventory so how can you access a numbered object in mongodb statmenets? What are you trying to do ? Insert empty objects into an array?

If yes this is done via a $push operator:

await client.db.userdata.updateOne({
            id: targetUser.id,
            }, {
            $push : {`inventory.${itemAdded.internalName}`: {quantity : 1} }
        })
...

Also for all the others, do same opertion without specifying array numbers…

Thanks,
Pavel

Instad of if (!userdata.inventory[itemAdded.internalName][ 1 ]) I think you should just ask if (!userdata)

The thing is, this is not the only thing I store about users. Their userdata profile could exist without this property existing in it.

There is no array elements in inventory so how can you access a numbered object in mongodb statmenets?

There are no arrays at all. Inventory is an object, with other objects in them (itemAdded.internalName in this case), which have other objects in them, called numbers. I’m trying to see if an object called 1 exists in userdata.inventory[itemAdded.internalName and if not, create it as a new object and add further properties to it

Here is an example of the structure

image

Ok I see,

This is not the best way to represent numeric positioning an you might hit lots of JS issues , why not to use arrays of objects which is the proper way.

If you have no option to change this data structI would than suggest you to first set the data into a variable and then test it. For example:

if (userdata.inventory) 
{
var internalName = userdata.inventory[itemAdded.internalName]["1"];
if (!internalName) {
...
}

But this is pure JS topic. I would suggest exploring using arrays instead of numeric fields…

Thanks,
Pavel

Thanks for the reply. I wouldn’t like to clutter up the forum with JS topics, so I’ll look into restructuring my database or using the solution you offered

1 Like