【问题标题】:Determine differences between incoming CSV data and existing Mongo collection for large data sets确定传入的 CSV 数据和现有的大型数据集 Mongo 集合之间的差异
【发布时间】:2021-02-05 03:37:36
【问题描述】:

我有一个传入的 CSV,我试图将它与现有的 mongo 文档集合(Note 对象)进行比较,以确定添加、删除和更新。传入的 CSV 和 mongo 集合非常大,每个都有大约 50 万条记录。

例如。 csv_data

[{
 id: 1, text: "zzz"
}, 
{
 id: 2, text: "bbb"
}, 
{
 id: 4, text: "ddd"
}, 
{
 id: 5, text: "eee"
}]

Note 对象的 Mongo 集合:

[{
 id: 1, text: "aaa"
}, 
{
 id: 2, text: "bbb"
}, 
{
 id: 3, text: "ccc"
}, 
{
 id: 4, text: "ddd"
}]

结果我想得到

添加的数组

[{
 id: 5, text: "eee"
}]

删除数组

[{
 id: 3, text: "ccc"
}]

一组更新

[{
 id: 1, text: "zzz"
}]

我尝试使用 select 语句来过滤每个特定差异,但在使用包含所有 500k 记录的真实数据集时它会失败/需要数小时。

additions = csv_data.select{|record| !Note.where(id: record[:id]).exists?}
deletions = Note.all.select{|note| !csv_data.any?{|row| row[:id] == note.id}}
updates = csv_data.select do |record|
    note = Note.where(id: record[:id])
    note.exists? && note.first.text != record[:text]
end

如何更好地优化它?

【问题讨论】:

  • 阅读 N+1 个查询,这是一个反模式

标签: ruby-on-rails ruby mongodb


【解决方案1】:

假设:CSV 文件是数据库中在其他时间拍摄的数据的快照,您想要一个差异。

为了得到您想要的答案,您需要阅读数据库中的每条记录。现在,您有效地执行此操作 3 次,一次获取每个统计信息。这是 c.1.5m 数据库调用,如果数据库上的注释比文件中的注释多得多,则可能更多。我会按照以下步骤操作:

  1. 将 CSV 数据读入以 ID 为键的哈希中
  2. 读取数据库中的每条记录,并针对每条记录:
  3. 如果在 CSV 散列中找到 DB ID,请将其从散列移到 updates
  4. 如果在 CSV 哈希中找不到 DB ID,请将其添加到 deletes
  5. 当您到达数据库的末尾时,CSV 哈希中仍然存在的任何内容都必须是 addition

虽然它仍然不是超级流畅,但至少您只需执行一次数据库 I/O 而不是 3 次...

【讨论】:

    猜你喜欢
    • 2011-11-11
    • 2010-09-08
    • 1970-01-01
    • 2018-06-13
    • 2017-08-07
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多