mongoDB 中的字符串字段值长度
String field value length in mongoDB
该字段的数据类型为String。我想获取字段名称字符长度大于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
operator allows the use of aggregation expressions within the query language, thus you can leverage the use of $strLenCP
运算符检查字符串长度如下:
db.usercollection.find({
name: { $exists: true },
$expr: { $gt: [{ $strLenCP: '$name' }, 40] }
})
对于 MongoDB 3.4 和更新版本:
您还可以使用带有 $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
的聚合框架来“删除”条件为假的文档。
此操作类似于让 $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
使用效率更高的单个流水线阶段。
至于逻辑条件,有String Aggregation Operators that you can use $strLenCP
operator to check the length of the string. If the length is $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
运算符的另一种更快的方法是 $regex
运算符。考虑以下搜索
的模式
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
注意 - 来自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.
我有过类似的情况,但在我的情况下,字符串不是一级属性。它在 object 内。在这里我找不到合适的答案。所以我想与大家分享我的解决方案(希望这会帮助任何有类似问题的人)。
Parent Collection
{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}
例如:如果我们只需要获取 child 名称长度超过 10 个字符的集合。
db.getCollection('Parent').find({$where: function() {
for (var field in this.Child.name) {
if (this.Child.name.length > 10)
return true;
}
}})
这是 mongodb 中的一种方法,您可以实现此目的。
db.usercollection.find({ $where: 'this.name.length < 4' })
如果文档太多,使用 $where
和 $expr
的查询会很慢。
使用$regex
比$where
、$expr
快得多。
db.usercollection.find({
"name": /^[\s\S]{40,}$/, // name.length >= 40
})
or
db.usercollection.find({
"name": { "$regex": "^[\s\S]{40,}$" }, // name.length >= 40
})
本查询与
同义
db.usercollection.find({
"$where": "this.name && this.name.length >= 40",
})
or
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gte": [ { "$strLenCP": "$name" }, 40 ] }
})
我针对 collection.
测试了每个查询
# find
$where: 10529.359ms
$expr: 5305.801ms
$regex: 2516.124ms
# count
$where: 10872.006ms
$expr: 2630.155ms
$regex: 158.066ms
此查询将给出字段值和长度:
db.usercollection.aggregate([
{
$project: {
"name": 1,
"length": { $strLenCP: "$name" }
}} ])
该字段的数据类型为String。我想获取字段名称字符长度大于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
operator allows the use of aggregation expressions within the query language, thus you can leverage the use of $strLenCP
运算符检查字符串长度如下:
db.usercollection.find({
name: { $exists: true },
$expr: { $gt: [{ $strLenCP: '$name' }, 40] }
})
对于 MongoDB 3.4 和更新版本:
您还可以使用带有 $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
的聚合框架来“删除”条件为假的文档。
此操作类似于让 $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
使用效率更高的单个流水线阶段。
至于逻辑条件,有String Aggregation Operators that you can use $strLenCP
operator to check the length of the string. If the length is $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
运算符的另一种更快的方法是 $regex
运算符。考虑以下搜索
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
注意 - 来自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 withabc
.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.
我有过类似的情况,但在我的情况下,字符串不是一级属性。它在 object 内。在这里我找不到合适的答案。所以我想与大家分享我的解决方案(希望这会帮助任何有类似问题的人)。
Parent Collection
{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}
例如:如果我们只需要获取 child 名称长度超过 10 个字符的集合。
db.getCollection('Parent').find({$where: function() {
for (var field in this.Child.name) {
if (this.Child.name.length > 10)
return true;
}
}})
这是 mongodb 中的一种方法,您可以实现此目的。
db.usercollection.find({ $where: 'this.name.length < 4' })
如果文档太多,使用 $where
和 $expr
的查询会很慢。
使用$regex
比$where
、$expr
快得多。
db.usercollection.find({
"name": /^[\s\S]{40,}$/, // name.length >= 40
})
or
db.usercollection.find({
"name": { "$regex": "^[\s\S]{40,}$" }, // name.length >= 40
})
本查询与
同义db.usercollection.find({
"$where": "this.name && this.name.length >= 40",
})
or
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gte": [ { "$strLenCP": "$name" }, 40 ] }
})
我针对 collection.
测试了每个查询# find
$where: 10529.359ms
$expr: 5305.801ms
$regex: 2516.124ms
# count
$where: 10872.006ms
$expr: 2630.155ms
$regex: 158.066ms
此查询将给出字段值和长度:
db.usercollection.aggregate([
{
$project: {
"name": 1,
"length": { $strLenCP: "$name" }
}} ])