使用 PostgreSQL hstore for i18n

问题描述 投票:0回答:2

我正在为一个需要本地化支持的新项目建模 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 | ...                   | ...

有人对这种方法有经验吗?它似乎非常灵活且易于使用,但也许我在这里遗漏了一些重大缺点?

postgresql internationalization hstore
2个回答
3
投票

我也在项目中使用这种方法,我相信这是一个很好的决定,因为我可以轻松地向我的项目添加新语言,而无需编写代码或更新数据库架构

我还可以轻松地向这样的查询添加后备:

select coalesce(nullif(post_title -> :lang, ''), post_title -> 'en') from posts

此外,还有大量强大的 sql 函数可供您使用。


0
投票

是的,这是一个非常好的方法,可以使使用索引的搜索变得非常有效。前段时间我做了一些研究,研究如何为产品数据库创建一个易于搜索的多语言数据模型。最终得到了这种类型的模式:

缺点是您必须为每种支持的语言创建索引

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 集成。

© www.soinside.com 2019 - 2024. All rights reserved.