Моделирование многоязычных данных на MongoDB

Я пытаюсь моделировать свои объекты на MonogoDB и не знаю, как это сделать. Я создаю каталог товаров, который будет:

  • Частые изменения в каталоге продуктов. Массовую операцию можно делать еженедельно/две недели.
  • Информация о продукте находится на нескольких языках (английском, испанском, французском), новый язык может быть добавлен в любое время.

Вот что я пытаюсь сделать: мне нужно смоделировать мой каталог продуктов, чтобы захватить многоязычную функциональность. Предположим, что у меня есть:

product : { 
 _id:xxx,
 sku:"23456",
 name:"Name",
 description: "Product details", 
 tags:["x1","x2"]}... 
}

Конечно, имя, описание, теги и возможные изображения будут меняться в соответствии с языком. Итак, как мне его моделировать?

  • У меня может быть отдельная коллекция для каждого языка, например: enProducts, esProducts и т.д.
  • Представление JSON в самом продукте с отдельными языками, например:

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


Или есть другое решение? Нужна помощь экспертов по моделированию MongoDB здесь:)

Ответ 1

Оба решения обычно являются стандартными для этого, причем первый из них является стандартным для техников RDBMS (или переводы на основе файлов являются другим методом, который здесь невозможен).

Как лучше всего здесь, я склоняюсь ко второму, рассматривая ваше использование.

Некоторые из причин:

  • Загрузка одного документа для всех переводов и данных продукта, без JOINs
  • Создание единого непрерывного чтения вашего диска
  • Разрешение для атомного обновления и добавления новых языков и изменений и т.д. к одному продукту

Но создание некоторых недостатков:

  • Обновление может (возможно, будет) создавать фрагментацию, которая может быть исправлена ​​в некоторой степени (не полностью) с помощью powerof2sizes
  • Теперь все ваши операционные системы перейдут к одной части вашего жесткого диска, которая может фактически создать бутылочную горловину, но ваш сценарий таков, что вы не обновляете часто, если вообще это не должно быть проблемой.

В качестве побочного примечания: я сужу, что фрагментация может не быть слишком большой проблемой для вас. Причина в том, что вы только на самом деле массовые импортные товары, возможно, из CSV, поэтому ваши документы, вероятно, не будут расти больше, чем сила 2 от их вставки на регулярной основе. Таким образом, этот момент может быть устаревшим.

Таким образом, в целом, если планировать правильно, второй вариант является хорошим, однако есть некоторые соображения, которые необходимо учитывать:

  • Может ли несколько описаний/полей удалять документ за пределы 16meg?
  • Как вручную вставить документ в документ, чтобы эффективно использовать пространство и предотвратить фрагментацию?

Это ваши самые большие проблемы, если вы поедете со вторым вариантом.

Учитывая, что вы можете поместить все работы Shakespear в 4MB с запасными местами, я действительно не уверен, достигнет ли вы предела 16 МБ, если вы это сделаете, это должно быть значительным текстом и, возможно, хранить изображения в двоичном формате в документе.

Возвращаясь к первому варианту, ваша самая большая проблема будет заключаться в дублировании определенных данных, то есть цена (у Франции и Испании есть евро), если вы не используете два документа, один для размещения общих данных, а другой - перевод (это будет сделайте 4 документа на самом деле, но два запроса).

Учитывая, что этот каталог никогда не будет обновляться, если объемные дублированные данные не будут иметь большого значения (однако для будущей ссылки в случае расширения я буду осторожен), так:

  • Вы можете сделать его одним документом на перевод, а не беспокоиться об обновлении цен атомарно во всех регионах.
  • У вас есть один диск без фрагментации
  • Вам не нужно вручную размещать ваши документы.

Таким образом, оба варианта доступны, но я склоняюсь ко второму случаю.

Ответ 2

Другой вариант - просто сохранить значения, разные для каждого языка. Возможно, упростит и упрощение схемы:

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"
 }  
}

und будет коротким для "undefined", то есть для всех языков, и может использоваться как резерв - или вы всегда используете "en" в качестве резервной, если хотите.

В приведенном выше примере показано, как Drupal CMS управляет языками (хотя и переведен с SQL на Mongo).

Ответ 3

Еще один вариант заключается в том, чтобы хранить ваши первичные данные только на одном языке и иметь отдельную сборку перевода текстовых ресурсов, где вы сопоставляете любой текстовый ресурс с вашего основного языка на другие целевые языки (независимо от того, что ваш текстовый ресурс поступает из первичное хранилище данных или просто перевод системного сообщения в вашу систему).

т.е. не вносите никаких языковых настроек в схему и модель вообще.

Недостаток, который я вижу, заключается в поддержании удаления информации из коллекции перевода, когда продукт удаляется из основного хранилища, ну, как только вы гарантируете, что тот же ресурс не используется в другом месте, он тривиален, но нуждается в для программирования:)

Ответ 4

Для статического списка языков я бы пошел с решением @Zagorulkin Dmitry, так как его легко запросить.

Для динамического списка языков я бы предпочел не изменять схему и упрощать управление данными.

Нижняя сторона - это то, что запрос менее тривиален.

  {
    "product": {
      "id": "xxx",
      "languageDependentData": [
        {
          "language": "en",
          "name": "Name",
          "description": "product details.."
        },
        {
          "language": "es",
          "name": "Name",
          "description": "product details.."
        }
      ]
    }
  }

Ответ 5

этот путь будет лучшим:

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

  }

только потому, что вам нужно искать только один продукт и после выбора любого языка.

Ответ 6

Как насчет этого подхода:

product: {
  id: 1,
  name: 'Original Name',
  description: 'Original Description',
  price: 33,
  date: '2019-03-13',
  translations: {
    es: {
      name: 'Nombre Original',
      description: 'Descripción Original',
    }
  }
}

Если пользователь выбирает какой-либо язык, отличный от языка по умолчанию, и в объекте существуют ключевые translations, вам нужно только объединить его, и если какой-либо ключ не имеет перевода, оригинал останется.

Еще одним преимуществом является то, что если вам нужно удалить функцию перевода или добавить/удалить какой-либо язык, вам нужно всего лишь изменить или удалить ключ перевода и не выполнять рефакторинг всей схемы.

Ответ 7

Я использую следующий шаблон для ключа и значений, которые должны быть проиндексированы в ключе:

 {
"id":"ObjectId",
"key":"error1"
"values":[{
             "lang":"en", 
             "value":"Error Message 1"
          },
          {
             "lang":"fa", 
             "value":"متن خطای شماره 1"
          }] 
}

и используйте этот код в С#

object = coleccion.find({"key": "error1"});

просмотрите эту ссылку Моделируйте отношения "один ко многим" со встроенными документами!