最佳方法导出Rails数据库数据

8

RAILS 5.1

我有一个使用PostgreSQL作为数据库的RAILS应用程序。我想从RAILS的角度导出/转储RAILS数据库数据,这样我就不依赖于数据库了。然后,我想使用此导出/转储文件将数据加载/导入/填充回数据库中。

我尝试过以下GEM:

  • seed_dump
    它可以工作,但无法处理HABTM模型关系。

  • yaml_db, 它可以工作,但YAML格式不是rails db:seed所理解的格式。


只需使用pg备份工具。"从RAILS的角度来看"这个说法听起来好像你在同一个数据库中存储了一堆其他的垃圾 - 不要这样做。 - max
不,我只在这个RAILS应用程序中使用这个数据库。没有其他一堆垃圾保存在这个数据库中。 pg备份工具将数据库数据存储在postgreSQL特定的sql转储格式中,不能用于加载到MySQL数据库中。 从“RAILS的角度”保存数据库数据时,这是一个巨大的优势。 - Sven Kirsten
如果你要部署到postgres,不要在测试/开发中使用mysql。你的开发环境应该尽可能地与生产环境相似。问题解决了。 - max
{btsdaf} - max
{btsdaf} - max
显示剩余2条评论
2个回答

7
这是一个导出JSON的实际示例。我使用rake任务来完成这种操作。在这个示例中,我正在转储用户表。
namespace :dataexport do
  desc 'export users who have logged in since 2017-06-30'
  task :recent_users => :environment do
    puts "Export users who have logged in since 2017-06-30"

    # Get a file ready, the 'data' directory has already been added in Rails.root
    filepath = File.join(Rails.root, 'data', 'recent_users.json')
    puts "- exporting users into #{filepath}"

    # The key here is to use 'as_json', otherwise you get an ActiveRecord_Relation object, which extends
    # array, and works like in an array, but not for exporting
    users = User.where('last_login > ?', '2017-06-30').as_json

    # The pretty is nice so I can diff exports easily, if that's not important, JSON(users) will do
    File.open(filepath, 'w') do |f|
      f.write(JSON.pretty_generate(users))
    end

    puts "- dumped #{users.size} users"
  end
end

然后导入

namespace :dataimport do
  desc 'import users from recent users dump'
  task :recent_users => :environment do
    puts "Importing current users"

    filepath = File.join(Rails.root, 'data', 'recent_users.json')
    abort "Input file not found: #{filepath}" unless File.exist?(filepath)

    current_users = JSON.parse(File.read(filepath))

    current_users.each do |cu|
      User.create(cu)
    end

    puts "- imported #{current_users.size} users"
  end
end

有时作为导入过程的一部分,我希望有一个干净的表格进行导入,这种情况下我会这样开始任务:
ActiveRecord::Base.connection.execute("TRUNCATE users")

这不是处理超过50,000行的非常大的表格和/或具有大量文本字段的最佳方法。在这种情况下,数据库本地转储/导入工具将更加适用。

为了完整起见,这里提供了一个HABTM示例。仍然有一个链接表,但它没有模型,因此唯一的处理方式是使用原始SQL。让我们想象一下我们的用户有许多角色,反之亦然(用户M:M角色),例如:

class User < ApplicationRecord
  has_and_belongs_to_many :roles
end

class Role < ApplicationRecord
  has_and_belongs_to_many :users
end

必然会有一个名为users_roles的连接表,其中将有两列:user_idrole_id请参阅HABTM的Rails指南

要导出,我们必须直接执行SQL:

users_roles = ActiveRecord::Base.connection.execute("SELECT * from users_roles").as_json
# and write the file as before

并执行SQL导入

# read the file, same as before
user_roles.each do |ur|
  ActiveRecord::Base.connection.execute("insert into users_roles (user_id, role_id) values ('#{ur[0]}', '#{ur[1]}')")
end

有关使用原始SQL插入的更多信息,请参见此答案


{btsdaf} - Sven Kirsten
{btsdaf} - rbb
{btsdaf} - Sven Kirsten
关于HABTM,我不喜欢它,而且我试过一次后就在30分钟后将其删除了。它与has_many/through相比没有特别的优势,却有一些明显的缺点,比如,连接表没有模型。要对其进行任何操作,你只能使用原始的SQL语句,这没问题,但我更喜欢让ActiveRecord来完成这项工作。尽管如此,我已经更新了答案。 - rbb
非常感谢您完成了这个基于JSON的转储/加载方法。对于我的RAILS应用程序,我对HABTM感到很满意,它运行得非常好。当我想从RAILS角度转储完整的RAILS数据库数据时,我被迫采用这种原始的SQL方式,以包括HABTM隐藏的连接表。但是,我有一个优势,可以编辑基于JSON的备份文件,并通过rails任务重新加载完整的RAILS应用程序。 - Sven Kirsten

1
我同意使用内置的数据库工具进行操作。或者查找一种方法告诉数据库将其导出为CSV,然后以这种方式导入。然而,如果您真的想要一种与数据库无关的方法,那么这里还有另一种方法:使用自己的API。我的意思是,在2017年,您的Rails应用程序不仅应该输出HTML,还应该输出JSON。也许您将来想编写SPA类型的应用程序或移动应用程序。确保对象除了HTML版本外还有Javascript表示,是一个好主意。所以,如果在您的应用程序中有/projects,请编写一个请求/projects的脚本作为JSON。将每个对象保存为自己的文件,然后在远程系统中将所有内容发回来。如果JSON表示中没有任何信息(即您未列出项目上的所有用户),请确保也要命中这些端点并将所有内容保存到单独的JSON文件中。然后编写一个播放器脚本,向目标服务POST所有这些文件。
那是一种方法。另一种方法是完全用Ruby在ActiveRecord中编写 - 这可能对某些用户数据导出功能很有用,因此这也是一种很棒的方法,但在我看来,“我们能否为此构建JavaScript前端或移动应用程序?”通常比“用户能否获取其数据”更早地被问到;)

{btsdaf} - Sven Kirsten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接