0

我有一个邮件存档设置,它运行以下不返回任何结果的查询。它只是连续运行。下面的查询有什么问题吗

query:{ $or: [ { $or: [ { rcpt_to: /vpadmin@vp.local/i }, { to: /vpadmin@vp.local/i }, { cc: /vpadmin@vp.local/i } ] } ] }

结果是这样的吗?

[
    {
        "$or" : [
            {
                "rcpt_to" : /vpadmin@vp.local/i
            },
            {
                "to" : /vpadmin@vp.local/i
            },
            {
                "cc" : /vpadmin@vp.local/i
            }
        ]
    }
]

邮件存档应用程序在日志中显示以下内容,这些内容可以正常工作并返回结果。此搜索使用日期完成

Tue Aug 28 13:00:40 [conn3] query enkive.userWorkspaces ntoreturn:1 idhack  reslen:152 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.workspaces ntoreturn:1 idhack  reslen:567 0ms
Tue Aug 28 13:00:40 [conn3] insert enkive.searchQueries 0ms
Tue Aug 28 13:00:40 [conn3] insert enkive.searchResults 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.workspaces ntoreturn:1 idhack  reslen:567 0ms
Tue Aug 28 13:00:40 [conn3]   running multiple plans
Tue Aug 28 13:00:40 [conn3] update enkive.workspaces  query: { _id: ObjectId('502b861ee4b04443c5db0481'), CreationDate: new Date(1345029662391), ModifiedUpdate: new Date(1346155131079), Creator: "enkive", WorkspaceName: "Default Workspace", SearchResults: [ "50334ba3e4b06e22baa0f244", "50334bbce4b06e22baa0f247", "50334be0e4b06e22baa0f24a", "5034f31fe4b06e22baa0f2e1", "503c9b73e4b002566417e868", "503cb27be4b002566417e86b", "5034f298e4b06e22baa0f2cc", "50334c72e4b06e22baa0f259", "5034f334e4b06e22baa0f2e4", "503c9b37e4b002566417e862", "503c9b62e4b002566417e865", "5035f329e4b0f6af52a5bb6c" ] } 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.searchResults ntoreturn:1 idhack  reslen:202 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.searchResults ntoreturn:1 idhack  reslen:202 0ms
Tue Aug 28 13:00:40 [conn3]   running multiple plans
Tue Aug 28 13:00:40 [conn3] update enkive.searchResults  query: { _id: ObjectId('503cb2e8e4b002566417e870'), ExecutionTimestamp: new Date(1346155240232), ExecutedBy: "enkive", SearchResults: {}, Status: "QUEUED", SearchQueryId: "503cb2e8e4b002566417e86f", IsSaved: false } 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.emailMessages reslen:6496 nreturned:2 0ms
Tue Aug 28 13:00:40 [conn3] insert enkive.auditLog 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.searchResults ntoreturn:1 idhack  reslen:203 0ms
Tue Aug 28 13:00:40 [conn3]   running multiple plans
Tue Aug 28 13:00:40 [conn3] update enkive.searchResults  query: { _id: ObjectId('503cb2e8e4b002566417e870'), ExecutionTimestamp: new Date(1346155240237), ExecutedBy: "enkive", SearchResults: {}, Status: "RUNNING", SearchQueryId: "503cb2e8e4b002566417e86f", IsSaved: false } 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.emailMessages ntoreturn:1 idhack  reslen:2226 0ms
Tue Aug 28 13:00:40 [conn3] insert enkive.auditLog 0ms
Tue Aug 28 13:00:40 [conn3] query enkive.emailMessages ntoreturn:1 idhack  reslen:4306 0ms
Tue Aug 28 13:00:40 [conn3] insert enkive.auditLog 0ms

@sammaya 当我运行你给我的东西时,我得到以下信息

> db.emailMessages.find( { $or : [ {"rcpt_to" : vpadmin@vp.local}, {"cc" : vpadmin@vp.local}, {"to" : vpadmin@vp.local} ]} );
Tue Aug 28 17:26:10 SyntaxError: missing } after property list (shell):1
4

4 回答 4

2

让我们谈谈为什么这个查询很慢。

你的数据集有多大?

您对这些字段中的任何一个都有索引吗?

由于您的查询中有一个 or 语句和一个正则表达式,因此可能需要一段时间才能运行,特别是如果您有一个相当大的数据集。

在你说“永不回来”之前,你等了多久?

你不能这样重写查询吗?

db.emailMessages.find( { $or : [ {"rcpt_to" : /vpadmin@vp.local/i},
                                 {"cc" : /vpadmin@vp.local/i}, 
                                 {"to" : /vpadmin@vp.local/i} 
                               ] 
                        } 
                      ) 

也可以尝试向这些字段添加一些索引:

db.emailMessages.ensureIndex( { rcpt_to: 1, cc: 1, to: 1 }, { background: true } )

此外,您可能希望编写一个 mongo map/reduce 作业来执行此查询,而不是使用查询语言或添加任何索引。无论如何,您都需要进行全表扫描来查询这些数据,而 map reduce 是一种更好的处理方式。

这是 mongodb map/reduce 的链接: http ://www.mongodb.org/display/DOCS/MapReduce

编辑:

我根据另一个答案更改了索引创建,因为他是正确的,mongo 只会使用一个索引进行查询。

于 2012-08-28T14:24:19.407 回答
2

这通常发生的原因是查询中的速度问题。

您正在使用带有索引不友好正则表达式的嵌套 $or。

现在没有任何前置正则表达式不使用索引(http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions)并将强制进行全表扫描。嵌套的 $or 子句也不使用索引:https ://jira.mongodb.org/browse/SERVER-3327因此您的查询正在扫描可能是非常非常大的表。

由于它是一个邮件存档设置,我会说它可以扫描数百万份文档。这就是为什么您没有得到响应并且查询只是永远“运行”的原因。

您可以尝试稍微更改架构以提高性能。首先,您可以省略嵌套的 $or 并且您可能会在邮件的标题字段中拆分电子邮件地址以进行搜索,这样您就可以进行更类似于以下的查询:

db.emailMessages.find( { 
    $or : [ {"rcpt_to" : vpadmin@vp.local},
            {"cc" : vpadmin@vp.local}, 
            {"to" : vpadmin@vp.local} ]
} ) 

您在此处查询的字段可能是电子邮件地址数组,这可以正常工作。在此之后,您需要设置正确的索引,如@Macdiesel 所说:

db.emailMessages.ensureIndex( { rcpt_to: 1, cc: 1, to: 1 }, { background: true } );

我在这里创建一个复合索引,因为 MongoDB 每个查询只能使用一个索引。

这不仅应该返回响应,而且不会杀死您的服务器,并且应该具有超级性能和可扩展性(大多数情况下,可能会进行更多改进)。

编辑

好的,所以一些澄清。

您需要像这样引用您的搜索字符串:

db.emailMessages.find( { 
    $or : [ {"rcpt_to" : "vpadmin@vp.local"},
            {"cc" : "vpadmin@vp.local"}, 
            {"to" : "vpadmin@vp.local"} ]
} ) 

由于除了这些字段中的一个之外的所有字段都可以是多个电子邮件地址,我建议您将其拆分ccto一组电子邮件地址,例如:

{
    _id: {},
    rcpt_to: "vpadmin@vp.local",
    cc: ["me@awesome.com", "you@kool.com"],
    to: ["another@notsokool.com"],
    message: "yo"
}

这当然只是一个示例模式,您需要使用它来获得您想要的东西,但它应该让您走上正确的轨道。

于 2012-08-28T14:46:30.517 回答
0

您缺少右括号。

query:{ $or: [ { $or: [ { rcpt_to: /vpadmin@vp.local/i }, { to: /vpadmin@vp.local/i }, { cc: /vpadmin@vp.local/i } ] } ]}
于 2012-08-28T10:50:58.267 回答
0

尝试以下查询。

db.content.find({$or : [{"rcpt_to" : /vpadmin@vp.local/i},{"cc" : /vpadmin@vp.local/i}, {"to" : /vpadmin@vp .local/i}]});

{$or : 
    [
        {"rcpt_to" : /vpadmin@vp.local/i},
        {"cc" : /vpadmin@vp.local/i}, 
        {"to" : /vpadmin@vp.local/i}
    ]
}
于 2012-08-28T11:18:27.183 回答