如何以可扩展的方式在数据库中作废(软删除)一条记录。

huangapple go评论65阅读模式
英文:

How to void (soft delete) a record in database in a scalable fashion

问题

目前我有一个名为 units 的表,包含以下列:

  • id:主键 整数
  • name:字符串
  • serial_id:字符串
  • ...

还有一个名为 statuses 的表。此单元的数据从我们的服务器发送到服务器。statuses 表包含以下列:

  • id:主键 整数
  • internal_temp:浮点数
  • battery_level:整数
  • unit_id:外键 整数
  • serial_id:字符串
  • ...

目前,我想要作废旧的单元,这样我就可以保存具有重复/相同 serial_id 的新单元。 但是,我仍然希望保持_作废的_ unitsstatuses 之间的关系,并以有组织、可扩展的方式维护关系/数据。

我的第一个想法是简单地在 units 表中添加 is_void,然后执行类似以下的操作:

Unit.where(serial_id: serial).find_by_is_void(false).statuses

但是,我不确定这是否会扩展得好。目前,每天一个 unit 大约生成2000条 status 记录。

我考虑过创建一个关联 unitstatus 之间关系的联接表,但我不确定,所以想寻求一些建议。

英文:

Currently I have a units table with the following columns:

  • id: PRIMARY Integer
  • name: String
  • serial_id: String
  • . . .

As well as a statuses table. This Unit's data is sent to the server from our server. The statuses table has the following columns:

  • id: PRIMARY Integer
  • internal_temp: Float
  • battery_level: Integer
  • unit_id: FOREIGN KEY Integer
  • serial_id: String
  • ...

Currently, I want to void out old units, so that way I can save new units with duplicate/same serial_id. However, I still want to preserve the relationship that voided units and statuses have and maintain the relationship/data in an organized, scalable manner.

My first idea, was to simply add is_void to the units table and then do something like:

Unit.where(serial_id: serial).find_by_is_void(false).statuses

but, I am not sure if this will scale well. Currently, a unit makes nearly 2000 status entries per day.

I was thinking along the lines of creating a join table that can manage the relationship between the unit and status but I was unsure and wanted to seek some advice.

答案1

得分: 2

如果您使用Rails 5或更低版本,您可以使用paranoia gem来实现软删除功能。这个gem要求我们在要软删除的模型中添加一个名为deleted_at的列。然后,它使用默认作用域(default scope)来仅获取那些尚未被软删除的记录。它提供了各种实用方法,以轻松获取已删除的记录,真正销毁记录等。

如果您使用Rails 6或想要自己实现软删除功能,以下是您需要执行的步骤:

  1. 在要软删除的模型中添加一个名为deleted_at的列。
  2. 在该模型中添加一个默认作用域,如 default_scope -> { where(deleted_at: nil) }
  3. 然后,您可以编写实用方法来检查记录是否已删除,或者创建范围(scopes)以获取已删除的记录。此API可以是您想要的任何内容。
  4. 为了可扩展性,您甚至可以将与软删除模型关联的所有常见方法提取出来,放入一个concern中,只需在需要的地方简单地插入即可。

正如您所看到的,这个实现与paranoia gem提供的功能非常相似。如果您正在学习并且有很多时间,我建议构建自己的功能。如果这是需要在专业项目中尽快部署的功能,我建议使用该gem,因为它可能会加快进程。

这是一篇描述paranoia gem及其功能的不错文章:Rails Soft Delete with Paranoia gem

英文:

If you're using Rails 5 or lower, you could use the paranoia gem to implement the soft delete functionality. This gem requires us to add a column called deleted_at to the model which we want to soft_delete. It then uses a default scope to fetch only those records which have not been soft deleted. It provides various utility methods to easily fetch deleted records, really destroy records etc.

In case you are using Rails 6 or want to implement the soft deletion feature by yourself, here's what you would need to do:

  1. Add a column called deleted_at to the model which you want to soft delete
  2. Add a default scope in that model as default_scope -> { where(deleted_at: nil) }
  3. You could then write utility methods to check if records are deleted or not, or scopes to fetch those records which are deleted as well. This API could be anything that you want
  4. For scalability, you could even extract out all the common methods that you would want, associated with soft deleted models, into a concern which could simply be plugged in wherever required

As you can see, this implementation is extremely similar to what the paranoia gem provides out of the box. In case you're doing this for learning and have lots of time, I'd recommend building your own feature. If this is something that needs to be deployed soon in a professional project, I'd recommend using the gem since it may speed up the process.

This is a nice article which describes the paranoia gem and its features: Rails Soft Delete with Paranoia gem

huangapple
  • 本文由 发表于 2020年1月6日 23:21:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/59614644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定