我的食物表有多种食物,每种食物可以具有多种语言(en、es)的特定属性,例如名称、描述等。但不确定所有属性是否始终针对该用户的首选语言存在,因此,如果首选语言不存在它们,我们可以从默认语言中选择属性,这样我们就可以确保我们始终有数据显示在我们的应用程序上,
这是我的 PostgreSQL 表结构
食物表:
食物_id | 能见度 |
---|---|
1 | 真实 |
性能表:
属性_id | 属性代码 |
---|---|
1 | 名字 |
2 | 描述 |
3 | 简短描述 |
食物特性表:
food_property_id | 食物_id | 属性_id | 价值 | 语言_id |
---|---|---|---|---|
1 | 1 | 1 | 英语中的食物名称 | en |
2 | 1 | 1 | es 中的食物名称 | 是 |
3 | 1 | 2 | 英语中的食物描述 | en |
4 | 1 | 2 | es 中的食物描述 | 是 |
5 | 1 | 3 | en 中的食物简短描述 | en |
6 | 1 | 3 | es 中的食物简短描述 | 是 |
案例1:
首选语言 - es ||默认语言 - en
所有 es 属性都存在 - 全部获取
结果:
食物特性表:
food_property_id | 食物_id | 属性_id | 价值 | 语言 ID |
---|---|---|---|---|
2 | 1 | 1 | es 中的食物名称 | 是 |
4 | 1 | 2 | es 中的食物描述 | 是 |
6 | 1 | 3 | es 中的食物简短描述 | 是 |
案例2:
首选语言 - es ||默认语言 - en
es 缺少属性 ID 2(描述)和 3(短描述),从默认语言 (en) 获取
食物特性表:
food_property_id | 食物_id | 属性_id | 价值 | 语言_id |
---|---|---|---|---|
2 | 1 | 1 | es 中的食物名称 | 是 |
3 | 1 | 2 | 英语中的食物描述 | en |
5 | 1 | 3 | en 中的食物简短描述 | en |
我希望您现在已经清楚这个想法:我们希望确保如果特定属性不存在,则以默认语言查找该属性,我 必须在应用程序中向使用不同语言的多个用户显示此食物列表,并且不能保证该食物的所有属性都存在。因此,我们可以显示默认语言的属性,只是为了确保应用程序上的所有数据始终看起来是填充的而不是空的。
我使用 PostgreSQL 作为数据库,使用 Java 进行编程,我对两种语言的解决方案都持开放态度,首选 Java,因为我在该级别使用了缓存层和过滤属性,我尝试了很多,但使用了太多循环来将每个项目与彼此,所以寻找优化的。
public class FoodTest {
class FoodProperties {
private String propertyCode;
private String value;
private String languageId;
// getters, setters, constructors
}
public static void main(String[] args) {
List<FoodProperties> foodProperties = new ArrayList<>();
FoodProperties p1 = new FoodProperties("1", "food name in en", "en");
FoodProperties p2 = new FoodProperties("1", "food name in es", "es");
FoodProperties p3 = new FoodProperties("2", "description in en", "en");
FoodProperties p4 = new FoodProperties("2", "description in es", "es");
FoodProperties p5 = new FoodProperties("3", "short desc in en", "en");
foodProperties.add(p1);
foodProperties.add(p2);
foodProperties.add(p3);
foodProperties.add(p4);
foodProperties.add(p5);
String preferredLanguage = "es";
String defaultLanguage = "en";
List<FoodProperties> result = new ArrayList<>();
for (FoodProperties foodProperty : foodProperties) {
String propertyCode = foodProperty.getPropertyCode();
Optional<FoodProperties> food = foodProperties.stream()
.filter(f -> f.getLanguageId().equals(preferredLanguage)
&& f.getPropertyCode().equals(propertyCode))
.findFirst();
if (food.isPresent()) {
result.add(food.get());
} else {
Optional<FoodProperties> foodDef = foodProperties.stream()
.filter(f -> f.getLanguageId().equals(defaultLanguage)
&& f.getPropertyCode().equals(propertyCode))
.findFirst();
if (foodDef.isPresent()) {
result.add(foodDef.get());
}
}
}
for (FoodProperties foodPropertiesData : result) {
System.out.println(foodPropertiesData);
}
}
}
仅选择几行时,您可以将表连接到自身并将数据保留为第一种可用语言
SELECT
coalesce(l1.food_property_id,l2.food_property_id) food_property_id,
coalesce(l1.food_id, l2.food_id) food_id,
coalesce(l1.property_id, l2.property_id) property_id,
coalesce(l1.value, l2.value) value,
coalesce(l1.language_id, l2.language_id) language_id
FROM food_properties l1
LEFT JOIN food_properties l2
ON l1.food_id = l2.food_id
AND l1.property_id = l2.property_id
AND l2.language_id = 999 --default_language_id
WHERE l1.language_id = 1 --ideal_language_id
请注意,如果您有两个表,一个用于通用属性,一个用于本地化属性,则此方法会更简单。