嗨,我在处理多个字段的搜索时遇到了问题。我有一个超过100万条记录的集合。当我在单个字段上执行操作时,它会产生闪光结果。但是当我尝试使用多个字段时,它就会折腾。我正在尝试使用如下匹配条件进行搜索:名字以' b'开头,姓氏以“' on'并通过电子邮件发送与" bwashington@zoombeat.net"。
的完全匹配我的收藏品类似于:
{
"_id": ObjectId("5391c81069f6872810004e49"),
"salutation": "frau",
"date_of_birth": ISODate("1970-01-01T00:00:00.0Z"),
"first_name": {
"0": {
"value": "Benjamin",
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"sweepstake": {
"sweepstake_id": "535e03888a06f83c12001380",
"sweepstake_url": "http:\/\/localhost\/redlemon\/sweepstakes\/register_user\/1\/53563bd68a06f8941300002b",
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"current_page": "1",
"session_id": "4ef315c35b5a1162eedc37fa109c3c57",
"last_activity": ISODate("2014-06-06T13:45:31.0Z")
}
}
},
"last_name": {
"0": {
"value": "Washington",
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"sweepstake": {
"sweepstake_id": "535e03888a06f83c12001380",
"sweepstake_url": "http:\/\/localhost\/redlemon\/sweepstakes\/register_user\/1\/53563bd68a06f8941300002b",
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"current_page": "1",
"session_id": "4ef315c35b5a1162eedc37fa109c3c57",
"last_activity": ISODate("2014-06-06T13:45:31.0Z")
}
}
},
"email": {
"0": {
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"sweepstake": {
"sweepstake_id": "535e03888a06f83c12001380",
"sweepstake_url": "http:\/\/localhost\/redlemon\/sweepstakes\/register_user\/1\/53563bd68a06f8941300002b",
"date_inserted": "2014-06-06 03:54:24",
"date_modified": "2014-06-06 03:54:24",
"current_page": "1",
"session_id": "4ef315c35b5a1162eedc37fa109c3c57",
"last_activity": ISODate("2014-06-06T13:45:31.0Z")
},
"email_id": "bwashington@zoombeat.net",
"email_optin_flag": "1",
"single_optin_flag": "1",
"double_optin_flag": "0",
"current_status": "active",
"suspicious_flag": NumberInt(0)
}
},
"last_inserted_date": ISODate("2014-06-06T13:54:24.0Z"),
"last_date_modified": ISODate("2014-06-06T13:54:24.0Z")
}
我在'引导'上添加了索引。收集为:
db.leads.ensureIndex({first_name:1},{sparse:true});
db.leads.ensureIndex({"last_name":1});
db.leads.ensureIndex({“email”:1});
db.leads.ensureIndex({"first_name.value":1});
db.leads.ensureIndex({"last_name.value":1});
db.leads.ensureIndex({"email.email_id":1});
当我使用currentOp()检查mongodb shell中的查询时,它看起来像:
"query" : {
"$query" : {
"first_name.value" : /^b/i,
"last_name.value" : /on$/i,
"email.email_id" : /^bwashington@zoombeat.net$/i
},
"$orderby" : { "last_inserted_date" : NumberLong(-1) }
}
答案 0 :(得分:1)
当您通过多个字段进行搜索时,查询速度较慢的原因是MongoDB没有使用索引(有效地)进行查询。
在2.6版本中,MongoDB获得了一个名为index intersection的新功能,它可以使用多个索引的交集来完成查询。虽然该功能非常有用,但使用复合索引可以获得更好的效果。
您还可以通过删除电子邮件上的正则表达式搜索来优化查询,并执行简单的相等检查,这比正则表达式更快:
{
"email.email_id" : "bwashington@zoombeat.net",
"first_name.value" : /^b/i,
"last_name.value" : /on$/i
}
您可以创建复合索引:
db.coll.ensureIndex({
"email.email_id" : 1,
"first_name.value": 1,
"last_name.value" : 1,
"last_inserted_date" : -1
});
last_inserted_date
日期在索引中,以便MongoDB可以在排序时使用它(如果排序操作消耗超过32MB,则会出现错误)。有关在排序数据时使用索引的详细信息,请查看documentation。
修改强>
由于格式错误,我没有看到文档的正确结构:)添加索引不起作用,因为您无法在两个数组上添加索引。
您的first_name
,last_name
和email
字段基本上是数组,但您应将它们转换为嵌入式文档。
"first_name": {
...
},
"last_name": {
...
},
"email": {
...
}
编辑2:
由于您无法转换数据结构,因此您的选项会减少。您无法在多个阵列字段上创建复合索引。要更好地解决此问题,您应该使用explain命令(可能在使用hint时)查看哪个索引的执行速度会更快。
答案 1 :(得分:0)
我认为Christian P.给出了最好的答案。复合索引将帮助您查询很多。
您还应该考虑另外一件事,您在查询中寻找什么信息?
如果您只需要一些可以缩小查询大小的字段,也许您可以尝试使用项目聚合框架。
如果您需要拥有这么多索引,请在查询中使用索引提示,以确保使用最佳索引。