mongoDB中的字符串字段值长度 [英] String field value length in mongoDB

查看:2855
本文介绍了mongoDB中的字符串字段值长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该字段的数据类型为字符串.我想获取字段名称的字符长度大于40的数据.

我尝试了这些查询,但返回错误. 1.

db.usercollection.find(
{$where: "(this.name.length > 40)"}
).limit(2);

output :error: {
    "$err" : "TypeError: Cannot read property 'length' of undefined near '40)' ",
    "code" : 16722
}

这在2.4.9中有效,但我的版本是2.6.5

解决方案

对于MongoDB 3.6及更高版本:

$expr 运算符允许在查询语言内使用聚合表达式,因此您可以利用


对于MongoDB 3.4及更高版本:

您还可以将聚合框架与 $redact 管道运算符,可让您使用

此操作类似于使用 $project 管道,该管道选择集合中的字段并创建一个新字段,该字段保存逻辑条件查询的结果,然后保存随后的 字符串聚合运算符您可以使用 $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 运算符,当您无法以任何其他方式构造数据或处理数据时, 一小部分数据.


一种避免使用 $where 运算符是

注意-从

如果正则表达式以."开头,则为前缀". 插入符(^)或左锚点(\A),后跟一串简单的字符串 符号.例如,正则表达式/^abc.*/将通过以下方式进行优化: 仅与索引中以abc开头的值匹配.

另外,当/^a/, /^a.*/,/^a.*$/匹配等效项时 字符串,它们具有不同的性能特征.所有这些 如果存在适当的索引,则表达式使用索引;然而, /^a.*//^a.*$/较慢. /^a/可以在扫描后停止扫描 匹配前缀.

The data type of the field is String. I would like to fetch the data where character length of field name is greater than 40.

I tried these queries but returning error. 1.

db.usercollection.find(
{$where: "(this.name.length > 40)"}
).limit(2);

output :error: {
    "$err" : "TypeError: Cannot read property 'length' of undefined near '40)' ",
    "code" : 16722
}

this is working in 2.4.9 But my version is 2.6.5

解决方案

For MongoDB 3.6 and newer:

The $expr operator allows the use of aggregation expressions within the query language, thus you can leverage the use of $strLenCP operator to check the length of the string as follows:

db.usercollection.find({ 
    "name": { "$exists": true },
    "$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] } 
})


For MongoDB 3.4 and newer:

You can also use the aggregation framework with the $redact pipeline operator that allows you to proccess the logical condition with the $cond operator and uses the special operations $$KEEP to "keep" the document where the logical condition is true or $$PRUNE to "remove" the document where the condition was false.

This operation is similar to having a $project pipeline that selects the fields in the collection and creates a new field that holds the result from the logical condition query and then a subsequent $match, except that $redact uses a single pipeline stage which is more efficient.

As for the logical condition, there are String Aggregation Operators that you can use $strLenCP operator to check the length of the string. If the length is $gt a specified value, then this is a true match and the document is "kept". Otherwise it is "pruned" and discarded.


Consider running the following aggregate operation which demonstrates the above concept:

db.usercollection.aggregate([
    { "$match": { "name": { "$exists": true } } },
    {
        "$redact": {
            "$cond": [
                { "$gt": [ { "$strLenCP": "$name" }, 40] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    { "$limit": 2 }
])


If using $where, try your query without the enclosing brackets:

db.usercollection.find({$where: "this.name.length > 40"}).limit(2);

A better query would be to to check for the field's existence and then check the length:

db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2); 

or:

db.usercollection.find({name: {$exists: true}, $where: "this.name.length > 
40"}).limit(2); 

MongoDB evaluates non-$where query operations before $where expressions and non-$where query statements may use an index. A much better performance is to store the length of the string as another field and then you can index or search on it; applying $where will be much slower compared to that. It's recommended to use JavaScript expressions and the $where operator as a last resort when you can't structure the data in any other way, or when you are dealing with a small subset of data.


A different and faster approach that avoids the use of the $where operator is the $regex operator. Consider the following pattern which searches for

db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2); 

Note - From the docs:

If an index exists for the field, then MongoDB matches the regular expression against the values in the index, which can be faster than a collection scan. Further optimization can occur if the regular expression is a "prefix expression", which means that all potential matches start with the same string. This allows MongoDB to construct a "range" from that prefix and only match against those values from the index that fall within that range.

A regular expression is a "prefix expression" if it starts with a caret (^) or a left anchor (\A), followed by a string of simple symbols. For example, the regex /^abc.*/ will be optimized by matching only against the values from the index that start with abc.

Additionally, while /^a/, /^a.*/, and /^a.*$/ match equivalent strings, they have different performance characteristics. All of these expressions use an index if an appropriate index exists; however, /^a.*/, and /^a.*$/ are slower. /^a/ can stop scanning after matching the prefix.

这篇关于mongoDB中的字符串字段值长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆