Where Query in MongoDB

Learn via video courses
Topics Covered

Overview

This article provides an overview of the $where in MongoDB. The $where operator in MongoDB allows you to write JavaScript expressions for querying MongoDB documents. However, its usage should be limited and considered as a last resort when other operators cannot express the desired query.

It is important to note that the $where in MongoDB does not have access to global variables or perform database operations. Queries using $where in MongoDB do not benefit from index usage, which can impact performance.

Therefore, it is recommended to use standard query operators whenever possible for better performance and query optimization. Consideration should also be given to alternative approaches, such as the aggregation framework, for complex data manipulations and aggregations.

Introduction to $where in MongoDB

The $where in MongoDB is a powerful query operator that allows you to perform JavaScript-based expressions within queries. It provides flexibility in querying by executing arbitrary JavaScript code on each document in a collection.

To use $where in MongoDB, you pass a JavaScript expression as a string to the operator. MongoDB will evaluate the expression for each document and return those for which the expression evaluates to true. The expression can access the document fields using this keyword.

Here's an example to illustrate the usage of $where:

It's worth noting that the $where the operator can be computationally expensive because it requires evaluating JavaScript expressions for each document. Therefore, it's recommended to use $where sparingly and consider other query operators or aggregation frameworks when possible, as they generally offer better performance.

Additionally, be cautious when using $where in MongoDB as it allows the execution of arbitrary code, which can introduce security risks if user-supplied input is directly used in the expression. It's important to ensure that the code is secure and well-validated to prevent potential vulnerabilities.

Note:

Starting from MongoDB 4.4, the $where operator has undergone changes. It no longer supports the deprecated BSON type JavaScript code with scope (BSON type 15). Instead, it only accepts BSON type String (BSON type 2) or BSON type JavaScript (BSON type 13). The use of BSON-type JavaScript code with scope has been deprecated since MongoDB 4.2.1. This means that when using $where in MongoDB, you should provide a string containing JavaScript code or a JavaScript object in the appropriate BSON format, rather than relying on the deprecated JavaScript code with scope format.

Behavior

The $where in MongoDB allows you to run JavaScript expressions within queries. It evaluates the expression for each document and includes those where the expression evaluates to true. However, $where in MongoDB can be computationally expensive and should be used sparingly. It's recommended to use specific query operators or the aggregation framework for better performance. Ensure the security of the JavaScript code used with $where by validating and sanitizing user input.

In map-reduce operations and $where operator expressions, there are limitations on accessing specific global functions or properties, like db, which are accessible in mongosh.

Properties and Functions

The following JavaScript functions and properties are available for use in map-reduce operations and $where operator expressions.

Available PropertiesAvailable Functions
argsassert()Map()
MaxKeyBinData()MD5()
MinKeyDBPointer()NumberInt()
DBRef()NumberLong()
doassert()ObjectId()
emit()print()
gc()printjson()
HexData()printjsononeline()
hex_md5()sleep()
isNumber()Timestamp()
isObject()tojson()
ISODate()tojsononeline()
isString()tojsonObject()
UUID()
version()

What is elemMatch?

The $elemMatch operator in MongoDB is used to query arrays based on specific criteria. It allows you to match documents where at least one element in an array field meets the specified conditions.

When using $elemMatch, you provide a query expression as its argument. MongoDB will then evaluate that expression against each element of the array field. If any element satisfies the conditions, the document is considered a match.

Here's an example to illustrate the usage of $elemMatch:

Explanation:

In this example, fieldName represents the array field you want to query, and criteria is the query expression to be applied to each element of the array.

The $elemMatch operator is particularly useful when dealing with arrays that contain embedded documents or multiple fields. It allows you to specify complex conditions on individual elements within the array.

Using $elemMatch ensures that the conditions are evaluated on the same element rather than matching different elements within the array independently. It allows for precise and targeted querying of array fields in MongoDB.

Considerations

When using the $where in MongoDB, there are several important considerations:

  • Avoid Global Variables:
    It's recommended to avoid using global variables within $where expressions. Since $where evaluates JavaScript code, global variables can introduce unexpected behavior and potential security risks.
  • Indexing Limitations:
    Queries using $where in MongoDB cannot take advantage of indexes. This means that the performance of $where queries may be significantly slower compared to queries that use standard MongoDB operators (e.g., $gt, $in) that can utilize indexes efficiently. Whenever possible, use standard query operators to improve query performance.
  • Minimize Usage of $where:
    $where in MongoDB should be used as a last resort when you cannot express your query using other operators. It is generally recommended to use standard query operators to leverage indexes and improve performance. If you must use $where in MongoDB, consider combining it with other operators to filter the result set and reduce the need for a collection scan.
  • Performance Advantage of Non-$where Statements:
    MongoDB evaluates non-$where components of a query before processing $where statements. If the non-$where statements match no documents, MongoDB can avoid performing any further query evaluation using $where. This can provide performance advantages in terms of query execution.
  • Index Usage in Non-$where Statements:
    Non-$where query statements have the potential to use indexes efficiently. By structuring your query using non-$where operators, you can take advantage of index optimization and improve query performance.

JavaScript Enablement for $where in MongoDB

To utilize operations like $where, \$function, \$accumulator, or mapReduce in MongoDB, you need to have server-side scripting enabled, which is enabled by (default).

However, if you do not use these operations, it is recommended to disable server-side scripting for security reasons. Here's how you can disable it:

For a "mongod" instance:

  • Check the security.javascriptEnabled configuration option. Set it to false to disable server-side scripting.
  • Alternatively, you can use the --noscripting command-line option when starting the mongod instance to disable scripting.

For a "mongos" instance:

  • Check the security.javascriptEnabled configuration option. Set it to false to disable server-side scripting.
  • Starting from MongoDB 4.4, you can also use the --noscripting command-line option when starting the mongos instance to disable scripting.

Unsupported Functions

Functions have either been deprecated or removed in newer versions of MongoDB's internal JavaScript engine. It is important to be aware of these unsupported functions to ensure compatibility and avoid any issues when working with strings and arrays in your MongoDB queries and expressions.

String

In MongoDB 6.0, the internal JavaScript engine used for server-side JavaScript, \$accumulator, \$function, $where, and other expressions have been upgraded from MozJS-60 to MozJS-91. As a result, several deprecated and non-standard string functions that existed in MozJS-60 are no longer supported in MozJS-91.

Array

Similar to the string functions, the upgrade to the internal JavaScript engine in MongoDB 6.0 (from MozJS-60 to MozJS-91) has also led to the removal of certain deprecated and non-standard array functions that were available in MozJS-60.

Examples

Suppose we have a collection named products with documents that have the following structure:

To find products with a price greater than or equal to 1000 using the $where operator, you can use the following query:

In this example, the $where operator allows you to write a JavaScript function that evaluates each document. The function checks if the price of the product (this.price) is greater than or equal to 1000. If the condition is met, the document will be included in the query results as mentioned below.

FAQs

Q. Can I use the $where operator to access global variables or database operations?

A. No, it is not recommended to use global variables or perform database operations within $where expressions. The $where operator is intended for evaluating JavaScript expressions on a per-document basis, and it does not have direct access to global variables or database functions like db.collectionName.find() or db.collectionName.aggregate(). It's best to use other MongoDB operators or the aggregation framework for such operations.

Q. Does the $where operator support index usage for query optimization?

A. No, the $where operator does not take advantage of indexes. Queries using $where typically require a collection scan, which can impact performance, especially for large collections. Whenever possible, it's recommended to use standard query operators like $eq, $gt, $in, etc., that can utilize indexes efficiently and improve query performance.

Conclusion

  • The $where in MongoDB allows you to write JavaScript expressions for querying MongoDB documents.
  • It should be used sparingly and as a last resort when other operators cannot express the desired query.
  • Avoid using global variables or performing database operations within $where expressions.
  • Queries using $where in MongoDB do not benefit from index usage, which can impact performance, especially for large collections.
  • Prefer using standard query operators like $eq, $gt, $in, etc., whenever possible for better performance and query optimization.
  • Review the specific functions and properties available within $where expressions in the MongoDB documentation.
  • Consider alternative approaches like the aggregation framework for complex data manipulations and aggregations.
  • Be mindful of the potential performance impact and optimize queries by combining $where in MongoDB with other operators to reduce the need for a collection scan.
  • Upgrade to the latest version of MongoDB to benefit from improvements and avoid deprecated features.