如何计算regex查询结果的计数?



我有一个大的MongoDB集合(大约)。30M条记录),每个项目都有一个由8位数字组成的唯一数字数组。大多数情况下,数组只有一个元素(一个数字)。例如,我想知道这个集合中以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,通过正则表达式查询索引字段的性能

我不确定,我没有比较和测试性能。,但尝试只^符号没有.*

{ "numbers.number": /^4/ }

根据MongoDB的regex索引使用文档中的附加说明,

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


第二个选项,我建议如果你知道数字的范围,你可以使用$gte$lt运算符通过指定数字来查找特定的系列,

{ 
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}

第三,您可以使用$or运算符检查多个范围,

{ 
"$or": [
{
"numbers.number": {
"$gte": "4000000",
"$lt": "5000000"
}
},
{
"numbers.number": {
"$gte": "40000000",
"$lt": "50000000"
}
}
]
}

注意:

  • 尝试在MongoDB shell中执行这个查询
  • 总是使用计数函数,如果你只需要文件的计数
    • db.coll.find({query}).count()
    • db.coll.countDocuments({query})

最新更新