对于MongoDB 3.6及更高版本:
该$expr
运营商将允许查询语言中使用聚合表达式,从而可以利用使用的$strLenCP
运营商来检查字符串的长度如下:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
对于MongoDB 3.4及更高版本:
您还可以将聚合框架与$redact
管道运算符一起使用,该运算符允许您通过运算符处理逻辑条件,$cond
并使用特殊操作$$KEEP
来“保留”逻辑条件为真的文档,或$$PRUNE
“删除”条件为真的文档。假。
这个操作类似于具有$project
管道,其选择所述集合中的字段,并创建保持从逻辑条件的查询结果的新字段,然后随后的$match
,所不同的是$redact
使用一个单一的流水线级,其是更有效的。
至于逻辑条件,可以使用“字符串聚合运算$strLenCP
符”来检查字符串的长度。如果长度是$gt
指定值,则这是真正的匹配,并且文档被“保留”。否则,将其“修剪”并丢弃。
考虑运行以下汇总操作,以证明上述概念:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
如果使用$where
,请尝试使用不带括号的查询:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
更好的查询是检查该字段的存在,然后检查长度:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
要么:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB$where
在$where
表达式和非$where
查询语句可以使用索引之前先评估非查询操作。更好的性能是将字符串的长度存储为另一个字段,然后可以对其进行索引或搜索。$where
相比之下,申请会慢很多。$where
当您无法以任何其他方式构造数据或处理少量数据时,建议使用JavaScript表达式和运算符作为最后的选择。
避免使用$where
操作员的另一种更快的方法是$regex
操作员。考虑以下搜索模式
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
注意-从文档中:
如果该字段存在索引,则MongoDB将正则表达式与索引中的值进行匹配,这可能比集合扫描更快。如果正则表达式是“前缀表达式”,则可能会发生进一步的优化,这意味着所有潜在的匹配都以相同的字符串开头。这允许MongoDB从该前缀构造一个“范围”,并且仅与索引中属于该范围的那些值匹配。
如果正则表达式以尖号(^)
或左锚(\A)
开头,然后是一串简单符号,则为“前缀表达式” 。例如,/^abc.*/
将仅通过匹配索引中以开头的值来优化正则表达式abc
。
此外,虽然/^a/, /^a.*/,
和/^a.*$/
匹配等效字符串,但它们具有不同的性能特征。如果存在适当的索引,则所有这些表达式都使用索引;但是,
/^a.*/
和/^a.*$/
较慢。/^a/
匹配前缀后可以停止扫描。