gpt4 book ai didi

mongodb - 对电子邮件集合进行高效索引,以便按电子邮件域进行排序和过滤

转载 作者:行者123 更新时间:2023-12-02 16:13:21 27 4
gpt4 key购买 nike

我使用 Mongoose 来保存电子邮件地址的集中集合,并且我还拥有用户和组织的集合。在我的应用程序中,我通过用户(经过验证的)电子邮件域将用户与组织关联起来。例如。 Acme Ltd 拥有域 acme.com 和 acme.co.uk,通过从使用这些域的所有电子邮件中进行选择,我可以整理一份唯一的关联用户列表。

用户可以拥有多个电子邮件地址(1 个主电子邮件地址 + 多个辅助电子邮件地址)。用户不能共享电子邮件地址(因此“verifiedBy”字段强制用户和电子邮件之间建立一对一的关系)。

我的架构(当前)如下:

const emailSchema = new Schema({
_id: {
type: String,
get: function idReverse(_id) { if(_id) return _id.split("@").reverse().join("@"); },
set: (str) => { str.trim().toLowerCase().split("@").reverse().join("@") }
},
verifiedBy: { type: String, ref: 'User' }
}, options );

My question is whether it is worth reversing the domain parts of the email address in the setter, and unreversing them in the getter - as I've shown - in order that the underlying MongoDb index on _id can improve performance & make it easier to deal with the kinds of lookups I've described?

我已经考虑过的替代方案是:

  • 按原样存储电子邮件并使用正则表达式按域部分选择用户(对我来说处理方面的成本很高)
  • 将域部分存储在单独的字段中并为其建立索引(感觉很昂贵,因为有两个索引和重复的数据存储)

最佳答案

第一个选项实际上应该效果很好。根据$regex docs :

[...] Further optimization can occur if the regular expression is a “prefix expression”, which means that all potential matches start with the same string. [...]

A regular expression is a “prefix expression” if it starts with a caret (^) or a left anchor (\A), followed by a string of simple symbols. [...]


实验

让我们检查一下它如何在包含约 80 万个文档的集合上运行,其中约 25% 有电子邮件。分析的示例查询为 {email:/^gmail/}

没有索引:

db.users.find({email: /^gmail/}).explain('executionStats').executionStats
// ...
// "nReturned" : 2208,
// "executionTimeMillis" : 250,
// "totalKeysExamined" : 0,
// "totalDocsExamined" : 202720,
// ...

使用 {email: 1} 索引:

db.users.find({email: /^gmail/}).explain('executionStats').executionStats
// ...
// "nReturned" : 2208,
// "executionTimeMillis" : 5,
// "totalKeysExamined" : 2209,
// "totalDocsExamined" : 2208,
// ...

正如我们所见,它绝对有帮助 - 无论是在执行时间还是检查的文档方面(检查的文档越多意味着可能需要更多的 IO 工作)。让我们看看如果我们忽略前缀并更直接地使用查询,它是如何工作的:{email:/gmail/}

没有索引:

db.users.find({email: /gmail/}).explain('executionStats').executionStats
// ...
// "nReturned" : 2217,
// "executionTimeMillis" : 327,
// "totalKeysExamined" : 0,
// "totalDocsExamined" : 202720,
// ...

使用 {email: 1} 索引:

db.users.find({email: /gmail/}).explain('executionStats').executionStats
// ...
// "nReturned" : 2217,
// "executionTimeMillis" : 210,
// "totalKeysExamined" : 200616,
// "totalDocsExamined" : 2217,
// ...

最后,索引有很大帮助,特别是在执行前缀查询时。看起来带前缀的查询足够快,可以在单个字段中保持原样。单独的字段可能可以更好地利用索引(使用它!),但我认为 5 毫秒就足够了。

一如既往,我强烈建议您对数据进行测试并查看其性能,因为数据特征可能会影响性能。

关于mongodb - 对电子邮件集合进行高效索引,以便按电子邮件域进行排序和过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59612714/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com