如何使用 ActiveRecord json 字段类型
How to use the ActiveRecord json field type
我有一个 Rails 模型,它有一个 "json" 类型的数据库列:
create_table "games", force: true do |t|
t.json "game_board"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
太棒了!现在我该如何使用它?真的就这么简单吗treating the field like a Hash
?
self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
如果我这样写,是否一切都会按预期工作,所以在将来 API 来自客户的电话中我可以这样做吗?:
self.game_board[:player] # And get back the 1 that I put here before
性能如何?即使从未读取过该字段,整个 game_board
每次都会被反序列化吗?每次我更改 "Hash?"
的一部分时,该字段是否会被重写(IOW 数据库写入)
是的,ActiveRecord 允许将 Postgres 的 json
-fields 简单地用作其模型中的 Hashes。但是,有几件事需要考虑:
Hash 在初始化时可能为 NULL
在您的 create_table
迁移中,您允许字段 :game_board
为 NULL
。因此,在第一次使用时,您的模型实例的字段 :game_board
将是 NULL
并且您必须在使用它之前先初始化哈希。 (见下面的例子)
在JSON中所有键都是字符串
因此,如果您之前使用过符号或数字,则在保存(和重新加载)时所有键都将转换为字符串。因此,为了防止不需要的行为,建议使用字符串键,除非您的 ORM 配置为符号化所有键。
你的例子:
self.game_board ||= {}
self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
# after reload from database (access via String-key):
self.game_board['player1'] # And retrieve value 1 (that we put here before)
@性能:
是的,每次 ActiveRecord 从数据库中读取条目并创建模型实例时,JSON-字段都会反序列化为哈希。但是,如果您认为这会影响您的应用程序的性能,那么您应该在需要时使用文本字段和 serialize/deserialize JSON/Hashes,或者更好的是,根本不要使用 ActiveRecord .通过创建 类 堆并使用魔术方法,ActiveRecord 产生了如此多的开销,您不必担心 JSON 的反序列化。便利是有代价的。
是的,每次更改哈希中的值时,(整个)JSON-字段都会被替换并更新为新的序列化版本。
两个注意事项:
- 即使在 Postgres 本身(不仅在 ActiveRecord 中),对某些 JSON 元素执行更新的可能性直到现在都是缺失的。 Compare this Whosebug-question
- 一般来说,JSON-字段应该与固定结构一起使用,或者至少以可管理的大小使用,并且字段类型不应该是文档存储,例如。在 MongoDB。 Compare the Postgres documentation
只是为了进一步说明 - 当您将 JSON 对象保存到模型实例的属性时 确保将其保存为散列。
Active Record 不会在您忘记解析 JSON string:
时报错
game = Game.create(game_board: '"key":"value"')
当您从 json
属性中检索字符串时,它不会抱怨,只会 return 字符串。
game.game_board
=> '"key":"value"'
因此 game.game_board['key']
会导致错误,因为您试图将字符串视为哈希。
因此请确保在保存前使用 JSON.parse(string)
。
game = Game.create(game_board: JSON.parse('"key":"value"'))
现在你有了预期的行为
game.game_board['key']
=> 'value'
可能对这种情况没有用,但是在从我正在集成的 API 中保存 JSON 有效载荷时遇到了这个问题。无论如何,希望这对您有所帮助。
我有一个 Rails 模型,它有一个 "json" 类型的数据库列:
create_table "games", force: true do |t|
t.json "game_board"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
太棒了!现在我该如何使用它?真的就这么简单吗treating the field like a Hash
?
self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
如果我这样写,是否一切都会按预期工作,所以在将来 API 来自客户的电话中我可以这样做吗?:
self.game_board[:player] # And get back the 1 that I put here before
性能如何?即使从未读取过该字段,整个 game_board
每次都会被反序列化吗?每次我更改 "Hash?"
是的,ActiveRecord 允许将 Postgres 的 json
-fields 简单地用作其模型中的 Hashes。但是,有几件事需要考虑:
Hash 在初始化时可能为 NULL
在您的create_table
迁移中,您允许字段:game_board
为NULL
。因此,在第一次使用时,您的模型实例的字段:game_board
将是NULL
并且您必须在使用它之前先初始化哈希。 (见下面的例子)在JSON中所有键都是字符串
因此,如果您之前使用过符号或数字,则在保存(和重新加载)时所有键都将转换为字符串。因此,为了防止不需要的行为,建议使用字符串键,除非您的 ORM 配置为符号化所有键。
你的例子:
self.game_board ||= {}
self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
# after reload from database (access via String-key):
self.game_board['player1'] # And retrieve value 1 (that we put here before)
@性能:
是的,每次 ActiveRecord 从数据库中读取条目并创建模型实例时,JSON-字段都会反序列化为哈希。但是,如果您认为这会影响您的应用程序的性能,那么您应该在需要时使用文本字段和 serialize/deserialize JSON/Hashes,或者更好的是,根本不要使用 ActiveRecord .通过创建 类 堆并使用魔术方法,ActiveRecord 产生了如此多的开销,您不必担心 JSON 的反序列化。便利是有代价的。
是的,每次更改哈希中的值时,(整个)JSON-字段都会被替换并更新为新的序列化版本。
两个注意事项:- 即使在 Postgres 本身(不仅在 ActiveRecord 中),对某些 JSON 元素执行更新的可能性直到现在都是缺失的。 Compare this Whosebug-question
- 一般来说,JSON-字段应该与固定结构一起使用,或者至少以可管理的大小使用,并且字段类型不应该是文档存储,例如。在 MongoDB。 Compare the Postgres documentation
只是为了进一步说明 - 当您将 JSON 对象保存到模型实例的属性时 确保将其保存为散列。
Active Record 不会在您忘记解析 JSON string:
时报错 game = Game.create(game_board: '"key":"value"')
当您从 json
属性中检索字符串时,它不会抱怨,只会 return 字符串。
game.game_board
=> '"key":"value"'
因此 game.game_board['key']
会导致错误,因为您试图将字符串视为哈希。
因此请确保在保存前使用 JSON.parse(string)
。
game = Game.create(game_board: JSON.parse('"key":"value"'))
现在你有了预期的行为
game.game_board['key']
=> 'value'
可能对这种情况没有用,但是在从我正在集成的 API 中保存 JSON 有效载荷时遇到了这个问题。无论如何,希望这对您有所帮助。