Fixing MongoDB's error "'$' by itself is not a valid FieldPath"

paulasantamaria

Paula Santamaría

Posted on May 5, 2020

Fixing MongoDB's error "'$' by itself is not a valid FieldPath"

I recently had to deal with a small issue working with update operations and aggregation pipelines in MongoDB. I couldn't find much help online to fix it, but I finally managed to understand it and decided to write my findings down to help anyone that may come across the same issue in the future.

The code

I was trying to create an update operation using aggregation pipelines on a Node.js project with mongoose. My code looked something like this:



// 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
        });
}


Enter fullscreen mode Exit fullscreen mode

The previous code is supposed to find a product by id and update its properties, setting the current date in the updatedAt property and concatenating the existent tags with some new tags.

Looks fine, right?

The error

But when I executed the update function, the following error was thrown by MongoDB:



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


Enter fullscreen mode Exit fullscreen mode

So after some debugging and tests I realized where the issue was. First let me show you how the product object that I was receiving in the arguments looked like:



{
    "name": "Lenovo Thinkbook 13s",
    "description": "The ThinkBook 13s laptop is a lightweight and durable, business laptop with amazing entertainment features.",
    "currency": "$",
    "price": 723,
    "newTags": [ "laptop", "lenovo" ]
}


Enter fullscreen mode Exit fullscreen mode

The issue was in the currency property value. The value was "$", which is a character used by MongoDB to identify field paths. So the error message was actually really clear, but it was not obvious for me at first sight.

The solution

Luckily the solution to this issue was pretty simple, I just had to use the $literal operator to wrap up my currency new value, like this:



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
        });
}


Enter fullscreen mode Exit fullscreen mode

About $literal

$literal is an aggregation pipeline operator that receives a value and makes sure the aggregation pipeline doesn't interpret it as a field path, and uses its literal value instead.

Read more about this operator in MongoDB's docs.

Test repo

I created a github repo to test the issue and its solution:

GitHub logo pawap90 / mongoose-literal-examples

A Node.js + Mongoose + Jest project that demonstrates how to use MongoDB's $literal operator to fix some common issues.

A Node.js + Mongoose + Jest project that demonstrates how to use MongoDB's $literal operator to fix some common issues.

This repo was build as an example for my article Fixing MongoDB's error "'$' by itself is not a valid FieldPath".

Dependencies

What you need to run this project:

  • Node.js

(MongoDB is not required because it'll run in memory by the package mongodb-memory-server).

Try it out

1. Install dependencies

npm install

2. Run tests

npm test

Contribute

Feel free to contribute to this project either by leaving your comments and suggestions in the Issues section or creating a PR.

Testing MongoDB in memory

To learn more about how this project executes tests on a dynamically generated database in memory, check my article Testing Node.js + Mongoose with an in-memory database






Thoughts? 💬

Have you ever come across this issue? Was this article useful?

💖 💪 🙅 🚩
paulasantamaria
Paula Santamaría

Posted on May 5, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related