【问题标题】:MongoDB Given a list of keys, get all matching docs and create new docs for non-matching keysMongoDB 给定一个键列表,获取所有匹配的文档并为不匹配的键创建新文档
【发布时间】:2013-10-06 23:45:20
【问题描述】:

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

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 查询返回数据库中未找到的电子邮件列表。然后我可以有效地插入新文档。否则,我必须遍历文档才能找到未收到的电子邮件。

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

【问题讨论】:

    标签: mongodb performance optimization database


    【解决方案1】:

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

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

    最佳方法可能取决于您的“缓存未命中率”,但如果现有匹配的数量不太高(伪代码),这应该可以工作

    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. 批量插入新创建的用户(即在客户端创建用户对象的列表或数组并将它们发送到数据库)

    这限制了到数据库的往返次数。由于查询是索引转换的,因此它将非常非常快,除非您的 RAM 已用尽并且索引不再适合 RAM。

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

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

    【讨论】:

    • 太棒了,这就是我要走的路。如果我想取回整个文档以供匹配的用户使用,您的答案会有什么变化?
    • 好吧,不多。只需交付所有数据。这样,查询将不会被覆盖,但如果您需要数据,则需要它。在第 2 步中,您可以像以前一样继续进行,只需要在进行集合减法时使用像 x -> x.email 这样的简单投影。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2020-06-07
    • 2021-08-03
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多