Home > OS >  Mongo DB remove 1 item from an array
Mongo DB remove 1 item from an array

Time:08-09

I have a buy system in place for my discord bot where it adds something to the inventory array in mongoDB:

data.Inventory[itemTobuy]   ;

It gets stored like this:

pizza: 1

And i have a use system where you can use items in your inventory. I would like to remove the whole thing if theres only 1 instance of this item but if there is more i would like to decrement the value by one. Say from pizza: 5 to pizza: 4. Althought im only 25% sure on how i would do such things

The full code for the command that adds the item if needed:

const { Client, Message, MessageEmbed } = require('discord.js');
const { User } = require("../../databasing/schemas/User")
const inventory = require('../../databasing/schemas/inventory')
const items = require('../../items/shopItems')

module.exports = {
    name: 'buy',
    /** 
     * @param {Client} client 
     * @param {Message} message 
     * @param {String[]} args 
     */
    run: async(client, message, args) => {
        userData = await User.findOne({ id: message.author.id }) || new User({ id: message.author.id })
        const itemTobuy = args[0].toLowerCase()
        embed = new MessageEmbed({ color: "#2F3136" })
        if(!args[0]) return message.channel.send({
            embeds: [ embed.setTitle('<:redCross:1004290018724020224> | Please mention something to buy!')]
        });
        const itemid = !!items.find((val) => val.item.toLowerCase() === itemTobuy);
        if(!itemid) return message.channel.send({
            embeds: [ embed.setTitle(`<:redCross:1004290018724020224> | ${itemTobuy} is not a valid item!`)]
        });
        itemPrice = items.find((val) => val.item.toLowerCase() === itemTobuy).price;
        userBalance = userData.wallet;
        if(userBalance < itemPrice) return message.channel.send({
            embeds: [embed.setTitle(`<:redCross:1004290018724020224> | You dont have enough money to buy this item(LOL)`)]
        }); 
        const param ={
            User: message.author.id
        }
        inventory.findOne(param, async(err, data) => {
            if(data){
                const hasItem = Object.keys(data.Inventory).includes(itemTobuy);
                if(!hasItem){
                    data.Inventory[itemTobuy] = 1;
                } else {
                    data.Inventory[itemTobuy]   ;
                }
                await inventory.findOneAndUpdate(param, data);
                } else {
                new inventory({
                    User: message.author.id,
                    Inventory: {
                        [itemTobuy]: 1,
                    }
                }).save()
                }
                message.channel.send({
                    embeds: [embed.setTitle(`<:greenTick:1004290019927785472> | Successfully bought ${itemTobuy}!`)]
                });
                userData.wallet -= itemPrice;
                userData.save()
        })
    }
}

CodePudding user response:

You can use $inc method to decrease the value of your item. For example:

const param = {
  User: message.author.id
}

const item_name = args.splice(0).join(" ").toLowerString();
//Take note that .toLowerString() will transform any string to lowercase.
//If your data is case sensitive, remove the .toLowerString().

inventory.findOne({
   param, //User.id
   "Inventory.name": item_name //Change the "name" to something on how you call the name of your items.
}, async(err, data) => {
   //Take note that we only identify if the item existing or not.
  if(data) {
    //Here's where you decrease the amount of the item.
    await inventory.findOneAndUpdate({
      param,
      "Inventory.name": item_name
    }, {
       $inc: {
         "Inventory.$.value": -1 //Change the value on how you call the value of your item
       }
    })
  } else {
    //Here is where you send a message that the item doesn't exist.
  }
})

EDIT:

To get the name and the value of your item, you need to find the curtain name.

First you need to create your inventory as array.

const inv = await inventory.findOne({
  param
})

const arr = inv.Inventory;

Your const arr = inv.Inventory; will make it to be an array. Then next step. Find the name

const item_name = args.splice(0).join(" ").toLowerString();
const inv = await inventory.findOne({
  param
})

const arr = inv.Inventory;
const item = arr.find(x => x.name == item_name);

After you get the item_name. You can now get the value and the name aswell and post it in somewhere you wanted. Can be embed or normal message.

const item_name = args.splice(0).join(" ").toLowerString();
const inv = await inventory.findOne({
  param
})

const arr = inv.Inventory;
const item = arr.find(x => x.name == item_name);

const items_value = item.value;
const items_name = item.name;

const embed = new MessageEmbed()
.addFields(
  {name: `Name:`, value: `${items_name}`},
  {name: `Value:`, value: `${items_value}`}
)

message.channel.send({embeds: [embed]})
  • Related