Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Docs 菜单
Docs 主页
/ /

$expr(查询谓词操作符)

5.0 版本中的更改

$expr

允许在查询谓词中使用 表达式

可以使用 $expr 查找托管在以下环境中的部署:

  • MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务

{ $expr: { <expression> } }

参数可以是任何有效的表达式。

$expr 出现在属于 $lookup 子管道的 $match 阶段时, $expr 可以引用 $lookup 阶段定义的 let 变量。有关示例,请参见使用多个连接条件和关联子查询

放置在 $expr 操作符上的 $eq$lt$lte$gt$gte 比较操作符可以使用 $lookup 阶段引用的 from 集合上的索引。限制:

  • 索引只能用于字段和常量之间的比较,因此 let 操作数必须解析为常量。

    示例,$a 和常量值之间的比较可以使用索引,但 $a$b 之间的比较不能使用索引。

  • let 操作数解析为空值或缺失值时,索引不用于比较。

  • 不使用 多键部分稀疏 索引。

本页上的示例使用sample_mflix示例数据集中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载示例数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。

$expr 可以包含对同一文档中的字段进行比较的表达式。

The following operation uses $expr to find documents in the movies collection where the Rotten Tomatoes viewer rating exceeds the critic rating:

db.movies.find(
{ $expr: { $gt: [ "$tomatoes.viewer.rating", "$tomatoes.critic.rating" ] } },
{ _id: 0, title: 1, "tomatoes.viewer.rating": 1, "tomatoes.critic.rating": 1 }
).sort( { "tomatoes.viewer.rating": -1 } ).limit( 3 )
[
{ title: 'I Am Maria', tomatoes: { viewer: { rating: 5 } } },
{ title: 'Kadin Hamlet', tomatoes: { viewer: { rating: 5 } } },
{ title: 'The Seine Meets Paris', tomatoes: { viewer: { rating: 5 } } }
]

Some queries need to execute conditional logic when defining a query filter. The aggregation pipeline provides the $cond operator to express conditional statements. By using $expr with the $cond operator, you can specify a conditional filter for your query statement.

Assume you want to calculate a weighted score for movies so that highly-rated movies with few votes do not dominate the results:

  • If imdb.votes is greater than or equal to 1000, the weighted score is the full imdb.rating.

  • If imdb.votes is less than 1000, the weighted score is 0.5 of the imdb.rating.

You would like to know which movies in the movies collection have a weighted score greater than 9.

The following example uses $expr with $cond to calculate the weighted score based on imdb.votes and $gt to return documents whose calculated weighted score is greater than 9:

db.movies.find(
{
"imdb.rating": { $type: "number" },
"imdb.votes": { $type: "number" },
$expr: {
$gt: [
{
$cond: {
if: { $gte: ["$imdb.votes", 1000] },
then: { $multiply: ["$imdb.rating", 1.0] },
else: { $multiply: ["$imdb.rating", 0.5] }
}
},
9
]
}
},
{ _id: 0, title: 1, "imdb.rating": 1, "imdb.votes": 1 }
).sort( { title: 1 } ).limit(5)

The following table shows the weighted score for selected documents and whether the weighted score is greater than 9 (i.e. whether the document meets the query condition).

文档
Weighted Score
> 9

{ title: "The Shawshank Redemption", imdb: { rating: 9.3, votes: 1521105 } }

9.3

true

{ title: "The Godfather", imdb: { rating: 9.2, votes: 1038358 } }

9.2

true

{ title: "Fight Club", imdb: { rating: 8.9, votes: 1191784 } }

8.9

false

{ title: "Planet Earth", imdb: { rating: 9.5, votes: 82896 } }

9.5

true

{ title: "Hollywood", imdb: { rating: 9.1, votes: 511 } }

4.55

false

The db.collection.find() operation returns 5 documents whose calculated weighted score is greater than 9:

[
{ title: 'Band of Brothers', imdb: { rating: 9.6, votes: 183802 } },
{ title: 'Baseball', imdb: { rating: 9.1, votes: 2460 } },
{ title: 'Cosmos', imdb: { rating: 9.3, votes: 17174 } },
{ title: 'Frozen Planet', imdb: { rating: 9.2, votes: 5903 } },
{ title: 'Human Planet', imdb: { rating: 9.2, votes: 9057 } }
]

Even though $cond calculates a weighted score, that score is not reflected in the returned documents. Instead, the returned documents represent the matching documents in their original state.

后退

其他

在此页面上