场合
我尝试设置数据库架构来存储不同语言之间的翻译。到目前为止它看起来像这样(简单):
class Language(models.Model):
tag = models.CharField(max_length=2)
def __unicode__(self):
return self.tag
class Phrase(models.Model):
name = models.TextField()
language = models.ForeignKey(Language)
def __unicode__(self):
return self.name
class Meta:
unique_together = ("name", "language")
index_together = [
["name", "language"]
]
class Translation(models.Model):
phrase1 = models.ForeignKey(Phrase, related_name="translation_as_1")
phrase2 = models.ForeignKey(Phrase, related_name="translation_as_2")
def __unicode__(self):
return self.phrase1.name + " <=> " + self.phrase2.name
class Meta:
unique_together = ("phrase1", "phrase2")
index_together = [
["phrase1", "phrase2"]
]
这个数据库架构对我来说似乎合情合理。我用不同的语言存储短语,然后翻译包含两个短语。
问题
问题是,由此架构产生的查询看起来很讨厌。例如:
from django.db.models import Q
name = "my phrase"
translations = Translation.objects.filter(Q(phrase1__name=text)|Q(phrase2__name=text))
translated_names = []
for translation in translations:
name1 = translation.phrase1.name
name2 = translation.phrase2.name
if name1 == name:
translated_names.append(name2)
else:
translated_names.append(name1)
我总是要包含“OR”关系,以确保我获得所有可能的翻译,因为短语可以存储为phrase1或phrase2。最重要的是,我必须在之后过滤我的结果以获得正确的translated_name(for循环)。
进一步说明
在我切换到所描述的架构之前,我改为使用以下架构(Phrase
和Language
与之前相同):
class Translation(models.Model):
phrase = models.ForeignKey(Phrase)
name = models.TextField()
def __unicode__(self):
return self.phrase.name + " => " + self.name
class Meta:
unique_together = ("phrase", "name")
index_together = [
["phrase", "name"]
这个架构让我可以这样进行查询:
from django.db.models import Q
name = "my phrase"
translations = Translation.objects.filter(phrase__name=text)
translated_names = [t.name for t in translations]
这看起来更好,当然更快。但是这个模式有缺点,它只在一个方向上呈现翻译,所以我转移到另一个,这也不是我想要的,因为查询太慢而且太复杂。
问题
对于这类问题,我是否有一个很好的架构,我可能会忽略它?
备注
我不仅对Django相关答案感兴趣。这种问题的纯SQL模式对我来说也很有趣。
答案 0 :(得分:0)
这是我过去做过的方式。根据您的命名惯例进行调整。
假设我有一个名称和其他列的表,就像这样
表 TR_CLT_clothing_type
clt_id | clt_name | other columns ....
--------------------------------------
1 | T Shirt ...
2 | Pants ...
现在如果我决定需要翻译,首先我要制作语言表
表 TR_LNG_language
lng_id | lng_name | lng_display
-------------------------------
1 | English | English (NZ)
2 | German | Deutsch
我还需要将当前语言存储在数据库中(您很快就会看到原因)。它只有一行
表 TA_INF_info
inf_current_lng
---------------
1
然后从服装表 TR_CLT_clothing_type 中删除 clt_name 列。而是我制作关系表。
表 TL_CLT_clothing_type
clt_id | lng_id | clt_name
--------------------------
1 | 1 | T Shirt
1 | 2 | (German for T-Shirt)
2 | 1 | Pants
2 | 2 | keuchen (thank you google translate)
现在要获取名称,您需要为其创建存储过程。我没有在ORM中尝试过这个。
CREATE PROCEDURE PS_CLT
@clt_id int
AS
SELECT lng.clt_name, clt.*
FROM TR_CLT_clothing_type clt
JOIN TL_CLT_clothing_type lng
ON lng.clt_id = clt.clt_id
WHERE clt.clt_id = @clt_id AND
lng.lng_id in (SELECT inf_current_lng FROM TA_INF_info)
此存储过程将返回当前语言的名称和指定语言的所有其他列。要设置语言,请在 TA_INF_info 表中设置 clt_current_lng 。
免责声明:我没有任何东西可以检查我输入的内容的语法,但它应该是直截了当的。
- 编辑
有人担心能够做到&#34;给我语言Y中的单词X翻译成语言Z&#34;
有一个&#34;不那么优雅&#34;使用模式执行此操作的方法。你可以做点什么
for each table in database like "TL_%"
SELECT name
FROM table
WHERE id IN ( SELECT id
FROM table
WHERE name = @name
AND lng_id = german
)
AND lng_id = english
现在我想这会需要一些自动生成的SQL代码,但我可以将其删除。
我不知道你将如何在ORM中做到这一点