我正在为一个需要本地化支持的新项目建模 PostgreSQL 数据库。我想知道 hstore 是否是本地化某些数据字段的好方法。
例如:让我们使用一个包含字段
post_title
和 post_content
的博客文章的简化表格。使用键值类型hstore,可以向这些字段添加多种翻译,并用语言代码作为键进行标识:
id | post_title (hstore) | post_content (hstore)
---|-----------------------|------------------------------
1 | "en" => "Hello World",| "en" => "Content in english",
| "de" => "Hallo Welt" | "de" => "Inhalt auf deutsch"
---|-----------------------|------------------------------
2 | ... | ...
有人对这种方法有经验吗?它似乎非常灵活且易于使用,但也许我在这里遗漏了一些重大缺点?
我也在项目中使用这种方法,我相信这是一个很好的决定,因为我可以轻松地向我的项目添加新语言,而无需编写代码或更新数据库架构
我还可以轻松地向这样的查询添加后备:
select coalesce(nullif(post_title -> :lang, ''), post_title -> 'en') from posts
此外,还有大量强大的 sql 函数可供您使用。
是的,这是一个非常好的方法,可以使使用索引的搜索变得非常有效。前段时间我做了一些研究,研究如何为产品数据库创建一个易于搜索的多语言数据模型。最终得到了这种类型的模式:
缺点是您必须为每种支持的语言创建索引
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX product_details_name_idx ON Product
USING GIN (lower(details_name_value) gin_trgm_ops);
CREATE INDEX product_translated_name_idx ON Product
USING GIN (lower(details_name_translationbylanguage -> 'pl') gin_trgm_ops);
但结果你得到了一个非常高效的执行计划:
explain select
product0_.id as id1_0_,
product0_.details_code as details_2_0_,
product0_.details_description_translationByLanguage as details_3_0_,
product0_.details_description_value as details_4_0_,
product0_.details_name_translationByLanguage as details_5_0_,
product0_.details_name_value as details_6_0_,
product0_.details_price as details_7_0_
from Product product0_
where lower(product0_.details_name_value) like ('%'||lower('aaa')||'%')
or lower(product0_.details_name_translationByLanguage -> 'pl') like ('%'||lower('aaa')||'%')
Bitmap Heap Scan on product product0_ (cost=175.84..5669.84 rows=15680 width=173)
Recheck Cond: ((lower((details_name_value)::text) ~~ '%aaa%'::text) OR (lower((details_name_translationbylanguage -> 'pl'::text)) ~~ '%aaa%'::text))
-> BitmapOr (cost=175.84..175.84 rows=16000 width=0)
-> Bitmap Index Scan on product_details_name_idx (cost=0.00..84.00 rows=8000 width=0)
Index Cond: (lower((details_name_value)::text) ~~ '%aaa%'::text)
-> Bitmap Index Scan on product_translated_name_idx (cost=0.00..84.00 rows=8000 width=0)
Index Cond: (lower((details_name_translationbylanguage -> 'pl'::text)) ~~ '%aaa%'::text)
甚至可以非常轻松地与 Javas JPA/Hibernate 中的 ORM 集成。