我有一个大的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})