Home > Net >  Mongoose update using dot notation and $ operator
Mongoose update using dot notation and $ operator

Time:12-25

I have a object that I want to update using findOneAndUpdate but it seems it's not working.. I already tried to use $ operator but it's not working but once I remove $ operator the call shows error of.

MongoServerError: Cannot create field 'categoryfilter' in element {store: [ { productname: "monitor", price: 1500, quantity: 5, categoryfilter: "Monitors", description: "tests", timestamp: "December 24th 2021, 1:39:36 pm", _id: ObjectId('61c55d687d8ff305de3ed044'), 0: { categoryfilter: "Monitors", description: "testsss", price: 1500, productname: "monitor", quantity: 5, timestamp: "December 24th 2021, 1:39:36 pm" } } ]}    at MessageStream.messageHandler (C:\Users\gamex\Desktop\my files\goldenwell\server\node_modules\mongodb\lib\cmap\connection.js:467:30)   
    at MessageStream.emit (events.js:376:20)   
    at processIncomingData (C:\Users\gamex\Desktop\my files\goldenwell\server\node_modules\mongodb\lib\cmap\message_stream.js:108:16)        
    at MessageStream._write (C:\Users\gamex\Desktop\my files\goldenwell\server\node_modules\mongodb\lib\cmap\message_stream.js:28:9)
    at writeOrBuffer (internal/streams/writable.js:358:12)
    at MessageStream.Writable.write (internal/streams/writable.js:303:10)
    at TLSSocket.ondata (internal/streams/readable.js:745:22)
    at TLSSocket.emit (events.js:376:20)       
    at addChunk (internal/streams/readable.js:309:12)
    at readableAddChunk (internal/streams/readable.js:284:9) {
  operationTime: new Timestamp({ t: 1640325515, i: 17 }),
  ok: 0,
  code: 28,
  codeName: 'PathNotViable',
  '$clusterTime': {
    clusterTime: new Timestamp({ t: 1640325515, i: 17 }),
    signature: {
      hash: new Binary(Buffer.from("c08511e0a3727ac6636aa2c56b4587cfcf0c2396", "hex"), 0),    
      keyId: new Long("7013342858887299079")   
    }
  }
}

here's my Schema I created using mongoose.

import mongoose from 'mongoose';

const OwnerSchema = mongoose.Schema({
    username: {
        require: true,
        type: String,
    },
    password: {
        require: true,
        type: String,
    },
    isAdmin: {
      type: Boolean,
      default: true,
    },
    store: [
        {
            productname: {
                type: String,
                required: true,
              },
            price: {
                type: Number,
                required: true,
              },
            quantity: {
                type: Number,
                required: true,
              },
            categoryfilter: {
              type: String,
              required: true
            },
            description: {
                type: String,
                required: true,
              },
            imageBase64: {
                type: String,
                required: true,
              },
            timestamp: {
              type: String,
              required: true,
            }
            
        }
    ]
});

const OwnerModels = mongoose.model('OwnerModels', OwnerSchema);

export default OwnerModels;

here's my query for update. I've tried to use $ operator but it seems no use at all so removed it.

export const updateProduct = async (req,res) => {

    const { id } = req.params;

    try {
        if(!mongoose.Types.ObjectId.isValid(id)) return res.status(404).json({ message: 'Invalid ID' });

        await OwnerModels.findOneAndUpdate({'_id': id, store:{ $elemMatch: { productname: req.body.store[0].productname }}},
            {$set: 
                {
                    "store.productname": req.body.store[0].productname,
                    "store.price": req.body.store[0].price,
                    "store.quantity": req.body.store[0].quantity,
                    "store.categoryfilter": req.body.store[0].categoryfilter,
                    "store.description": req.body.store[0].description,
                    "store.timestamp": req.body.store[0].timestamp 
                }
            }, 
            {new: true, safe: true, upsert: true}, (error, response) => {
                if(error){
                    console.log(error)
                }else{
                    console.log(response)
                }
            }
            );

    } catch (error) {
        res.status(404).json(error)
    }

}

CodePudding user response:

Because store is an array, mongodb cannot know which element in store to update by your { $set: { 'store.categoryfilter': ... } } statement.

The $elemMatch query is just for query filter at document level, it will not pick the specific store element out to update.

The right choice is to use arrayFilter in update statement

CodePudding user response:

Try to retrieve the OwnerModel with a findByid and then update the store array using the push method.
You will need to save the updated object using the save method.

const owner = await OwnerModels.findByid(id);
if (!owner) {
    return res.status(404).json({ message: "Owner not found" });
}
owner.store.push(req.body.store);
await owner.save();

res.status(200).json({ message: "Updated" })

Finally, you may want to add a default value to the imageBase64 field, since I don't see it listed in your body params:

imageBase64: {
    type: String,
    required: true,
    default: ""
},
  • Related