Paula Santamaría
Paula Santamaría

Reputation: 21

MongoDB "'$' by itself is not a valid FieldPath" when using Aggregation Pipeplines on an Update operation

I'm trying to execute an update operation using aggregation pipelines on a Node.js project with mongoose. Here's my code:

// Model schema
let productSchema = new Schema({
    name: { type: String, required: true },
    description: { type: String, required: false },
    currency: { type: String, required: false },
    price: { type: Number, required: true },
    createdAt: { type: Date, default: Date.now, required: true },
    updatedAt: { type: Date, required: false },
    tags: [String],
});

// Update operation
module.exports.update = async (product) => {

    await productModel.findByIdAndUpdate(product._id,
        [{
            $set:
            {
                name: product.name,
                description: product.description,
                currency: product.currency,
                price: product.price,
                updatedAt: '$$NOW',
                tags: { $concatArrays: [ '$tags', product.newTags  ] }
            }
        }],
        { 
            runValidators: true
        });
}

When I execut the update function, I get the following error:

{
    "ok": 0,
    "errmsg": "'$' by itself is not a valid FieldPath",
    "code": 16872,
    "codeName": "Location16872",
    "name": "MongoError"
}

Node.js version: 12.13

MongoDB version: 4.2.6

Upvotes: 1

Views: 1154

Answers (1)

Paula Santamaría
Paula Santamaría

Reputation: 21

Turns out the value I was receveing in product.currency was "$" and that was what was causing the error. To fix it I had to use the $literal operator to wrap up product.currency, like so:

module.exports.update = async (product) => {

    await productModel.findByIdAndUpdate(product._id,
        [{
            $set:
            {
                name: product.name,
                description: product.description,
                currency: { $literal: product.currency }, // <--- here!
                price: product.price,
                updatedAt: '$$NOW',
                tags: { $concatArrays: [ '$tags', product.newTags  ] }
            }
        }],
        { 
            runValidators: true
        });
}

According to the official MongoDB docs on $literal:

Returns a value without parsing. Use for values that the aggregation pipeline may interpret as an expression.

Upvotes: 1

Related Questions