如何计算正则查询结果的个数?
How to calculate the count of regex query results?
我有一个很大的 MongoDB 集合(大约 3000 万条记录),每个项目都有一个由 8 位数字组成的唯一数字数组。大多数情况下,该数组只有 1 个元素(1 个数字)。例如,我想知道集合中有多少条以 4 开头的记录,所以我查询:
{ "numbers.number": /^4.*/i }
但是查询时间太长了,上次我用了20分钟才中断执行。所以我想知道是否有一种方法可以优化查询。 numbers.number
已编入索引。我也试过这个:
{ "numbers.number": /^4[0-9]{7}/}
仍然需要很长时间。这是文档的示例:
{
"_id" : ObjectId("some_id"),
"created_at" : ISODate("2022-10-13T09:32:45.000+0000"),
"source" : {
"created_at" : ISODate("2021-10-13T08:54:06.000+0000"),
"some_id" : NumberInt(234),
"another_id" : NumberInt(11)
},
"first_name" : "Test",
"last_name" : "Test",
"date_of_birth" : "1970-01-01",
"status" : "active",
"numbers" : [
{
"created_at" : ISODate("2022-11-13T09:32:45.000+0000"),
"number" : "40000005",
"_id" : ObjectId("some_id")
}
]
}
正则表达式的性能和速度成本很高,即使它有索引也没有索引,如果你有数以百万计的数据,
这是一个类似的问题,MongoDB, performance of query by regular expression on indexed fields
我不确定,我还没有比较和测试性能。但是试试 ^
没有 .*
,
的符号
{ "numbers.number": /^4/ }
根据 MongoDB 的 regex index use documentation 中的附加说明,
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.
第二个选项,如果你知道数字的范围,我建议你可以使用 $gte
和 $lt
运算符通过指定数字来查找特定系列,
{
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}
第三,可以使用$or
运算符检查多个范围,
{
"$or": [
{
"numbers.number": {
"$gte": "4000000",
"$lt": "5000000"
}
},
{
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}
]
}
NOTE:
- try to execute this query in MongoDB shell
- always use count functions, if you just need counts of the documents
db.coll.find({query}).count()
db.coll.countDocuments({query})
我有一个很大的 MongoDB 集合(大约 3000 万条记录),每个项目都有一个由 8 位数字组成的唯一数字数组。大多数情况下,该数组只有 1 个元素(1 个数字)。例如,我想知道集合中有多少条以 4 开头的记录,所以我查询:
{ "numbers.number": /^4.*/i }
但是查询时间太长了,上次我用了20分钟才中断执行。所以我想知道是否有一种方法可以优化查询。 numbers.number
已编入索引。我也试过这个:
{ "numbers.number": /^4[0-9]{7}/}
仍然需要很长时间。这是文档的示例:
{
"_id" : ObjectId("some_id"),
"created_at" : ISODate("2022-10-13T09:32:45.000+0000"),
"source" : {
"created_at" : ISODate("2021-10-13T08:54:06.000+0000"),
"some_id" : NumberInt(234),
"another_id" : NumberInt(11)
},
"first_name" : "Test",
"last_name" : "Test",
"date_of_birth" : "1970-01-01",
"status" : "active",
"numbers" : [
{
"created_at" : ISODate("2022-11-13T09:32:45.000+0000"),
"number" : "40000005",
"_id" : ObjectId("some_id")
}
]
}
正则表达式的性能和速度成本很高,即使它有索引也没有索引,如果你有数以百万计的数据,
这是一个类似的问题,MongoDB, performance of query by regular expression on indexed fields
我不确定,我还没有比较和测试性能。但是试试 ^
没有 .*
,
{ "numbers.number": /^4/ }
根据 MongoDB 的 regex index use documentation 中的附加说明,
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.
第二个选项,如果你知道数字的范围,我建议你可以使用 $gte
和 $lt
运算符通过指定数字来查找特定系列,
{
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}
第三,可以使用$or
运算符检查多个范围,
{
"$or": [
{
"numbers.number": {
"$gte": "4000000",
"$lt": "5000000"
}
},
{
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}
]
}
NOTE:
- try to execute this query in MongoDB shell
- always use count functions, if you just need counts of the documents
db.coll.find({query}).count()
db.coll.countDocuments({query})