MongoDB上的多语言数据建模

Abd*_*oof 13 object-model mongodb

我试图在MonogoDB上建模我的对象,但不确定如何继续.我正在构建一个产品目录:

  • 不经常更改产品目录.批量操作可以每周/两周进行.
  • 产品信息有多种语言(英语,西班牙语,法语),可随时添加新语言.

以下是我要做的事情:我需要对产品目录进行建模以捕获多语言功能.假设我有:

product : { 
 _id:xxx,
 sku:"23456",
 name:"Name",
 description: "Product details", 
 tags:["x1","x2"]}... 
}
Run Code Online (Sandbox Code Playgroud)

当然,名称,描述,标签和可能的图像将根据语言而改变.那么,我该如何建模呢?

  1. 我可以为每种语言设置单独的集合,例如:enProducts,esProducts等
  2. 在产品本身中使用各种语言进行JSON表示:

    product :{
       id: xxx,
       en: {
             name: "Name",
             description: "product details.."
           },
       es: {
             name: "Name",
             description: "product details.."
           },
       ...   
    }
    
    Run Code Online (Sandbox Code Playgroud)


或者还有其他解决方案吗?在这里需要MongoDB建模专家的帮助:)

Ada*_*hel 16

另一种选择是保持每种语言的值不同。也可能会使维护架构更容易:

product : { 
 _id:xxx,
 sku: {
   und: "23456"
 },
 name: {
   en: "Fork",
   de: "Gabel"
 },
 description: {
   en: "A metal thingy with four spikes",
   de: "Eine Dinge aus metal der vier spitze hat"
 }  
}
Run Code Online (Sandbox Code Playgroud)

und 将是“undefined”的缩写,即所有语言都相同,并且可以用作后备 - 或者如果您愿意,您总是使用“en”作为后备。

上面的例子大致是 Drupal CMS 管理语言的方式(虽然是从 SQL 翻译成 Mongo)。


Dam*_*ian 14

这种方法怎么样:

product: {
  id: 1,
  name: 'Original Name',
  description: 'Original Description',
  price: 33,
  date: '2019-03-13',
  translations: {
    es: {
      name: 'Nombre Original',
      description: 'Descripción Original',
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果用户选择了与默认不同的语言,并且keytranslations存在于对象中,则只需将其合并即可,如果有key没有翻译,则保留原件。

另一个优点是,如果您需要删除翻译功能或添加/删除某些语言,您只需更改或删除翻译键,而不必重构整个架构。


Sam*_*aye 7

这两种解决方案通常都是标准的,第一种也是RDBMS技术的标准(或者基于文件的翻译是另一种在这里不可能的方法).

至于哪个最好就在这里,我倾向于考虑你的使用.

一些原因是:

  • 所有翻译和产品数据的单个文档加载,无JOIN
  • 对磁盘进行单个连续读取
  • 允许原子更新并向单个产品添加新语言和更改等

但是创造了一些缺点:

  • 更新可能(可能会)创建碎片,可以通过powerof2sizes在某种程度上(不完全)补救
  • 现在你的所有操作都会转到硬盘的一个部分,这实际上可能会创建一个瓶颈但是,你的场景是这样你不经常更新,所以这应该不是问题.

作为旁注:我认为碎片化可能对您来说不是太大的问题.原因是你只是真正批量导入产品,可能来自CSV,因此你的文件不会比定期插入的文件大2.因此,这一点可能已经过时.

总的来说,如果计划得当,第二种选择是好的,那么需要考虑一些因素:

  • 多个描述/字段是否可以将文档推送超过16meg限制?
  • 如何手动填充文档以有效利用空间并防止碎片?

如果你选择第二个选项,这些是你最关心的问题.

考虑到你可以将莎士比亚的所有作品都装入4MB,并且有余地,我实际上不确定你是否会达到16MB的限制,如果你这样做,则必须是一些相当大的文本,并且可能将图像以二进制形式存储到该文件.

回到第一个选项,你最大的担忧是重复某些数据,即价格(法国和西班牙都有欧元),除非你使用两个文件,一个用于存放公共数据,另一个用于翻译(这将产生4个文件)实际上,但两个查询).

考虑到这个目录永远不会更新,除非批量重复数据不会太重要(但是,为了将来参考扩展我会谨慎)所以:

  • 您可以使每个翻译都有一个文档,而不必担心在所有区域中以原子方式更新价格
  • 您有一个没有碎片的磁盘读取
  • 无需手动填充文档

因此,两种选择都很容易获得,但我倾向于第二种情况.


jav*_*iri 5

我对应在键中索引的键和值使用以下模式:

\n\n
 {\n"id":"ObjectId",\n"key":"error1"\n"values":[{\n             "lang":"en", \n             "value":"Error Message 1"\n          },\n          {\n             "lang":"fa", \n             "value":"\xd9\x85\xd8\xaa\xd9\x86 \xd8\xae\xd8\xb7\xd8\xa7\xdb\x8c \xd8\xb4\xd9\x85\xd8\xa7\xd8\xb1\xd9\x87 1"\n          }] \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

并在 C# 中使用此代码

\n\n
object = coleccion.find({"key": "error1"});\n
Run Code Online (Sandbox Code Playgroud)\n\n

查看此链接使用嵌入文档建立一对多关系模型!

\n


Dmi*_*kin 2

这种方式将是最好的:

product :{
       id: xxx,
       en: {
             name: "Name",
             description: "product details.."
           },
       es: {
             name: "Name",
             description: "product details.."
           },
       ...

  }
Run Code Online (Sandbox Code Playgroud)

只是因为您只需搜索一种产品,然后您就可以选择任何语言。