Mongodb集合不会搜索多个搜索

时间:2014-06-10 15:08:44

标签: php mongodb

嗨,我在处理多个字段的搜索时遇到了问题。我有一个超过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) } 
} 

2 个答案:

答案 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_namelast_nameemail字段基本上是数组,但您应将它们转换为嵌入式文档。

"first_name": {
    ...
},
"last_name": {
    ...
},
"email": {
    ...
}

编辑2:

由于您无法转换数据结构,因此您的选项会减少。您无法在多个阵列字段上创建复合索引。要更好地解决此问题,您应该使用explain命令(可能在使用hint时)查看哪个索引的执行速度会更快。

答案 1 :(得分:0)

我认为Christian P.给出了最好的答案。复合索引将帮助您查询很多。

您还应该考虑另外一件事,您在查询中寻找什么信息?

如果您只需要一些可以缩小查询大小的字段,也许您可​​以尝试使用项目聚合框架。

如果您需要拥有这么多索引,请在查询中使用索引提示,以确保使用最佳索引。