MongoDB给定一个键列表,获取所有匹配的文档并为非匹配键创建新文档

时间:2013-10-06 23:45:20

标签: mongodb performance optimization database

说我有一组用电子邮件地址索引的用户文档。给出一个电子邮件地址列表,我需要:

1. Get each User doc whose email is in that list
2. Create a new User doc for each email in the list for which no User exists.

我可以使用$ in查询轻松解决第一个问题,但我希望有一些方法可以让$ in查询返回数据库中找不到的电子邮件列表。然后我可以有效地插入新的文档。否则,我必须遍历文档以查找未接收的电子邮件。

完成上述两项任务的最有效方法是什么?有没有快速的方法从一组独特的电子邮件中批量插入新的用户文档?

1 个答案:

答案 0 :(得分:0)

  

我希望有一些方法可以让$ in查询返回数据库中找不到的电子邮件列表。

您可以使用$nin。很遗憾,$ne$nin can't make good use of indexes,这可能不是您最好的选择(但也许值得一试)。

最好的方法可能取决于你的'cache-miss-rate',但是如果现有匹配的数量不是太高(伪代码),这应该有效

var emails;
var matchingMails = users.find({"email" : {$in : emails}}, {"email":1, "_id":0});
var newEmails = emails.subtract(matchingMails); // set difference
db.batchInsert(createUsersFromEmails(newEmails));

  1. 使用$in查找具有匹配电子邮件地址的所有用户。确保只返回电子邮件字段本身,以便query is covered(即MongoDB只查看索引本身而不必扫描文档)

  2. 从列表中删除数据库中已有的所有电子邮件(快速简单字符串操作)

  3. 批量插入新创建的用户(即创建客户端用户对象的列表或数组并将其发送到数据库)

  4. 这限制了到数据库的往返次数。由于查询是索引控制的,除非你的RAM耗尽且索引不再适合RAM,否则它将非常非常快。

    明智的做法是在电子邮件地址上使用唯一索引,并允许批量插入完成,即使单个插入失败,以防有人在其间注册,或者有另一个线程运行此代码。

    $in查询的元素数量不应太高,根据经验,大概在1,000到10,000之间。