Подтвердить что ты не робот

Должен ли тег быть собственным ресурсом или вложенным свойством?

Я на перекрестке, решив, должны ли теги быть их собственным ресурсом или вложенным свойством заметки. Этот вопрос немного затрагивает дизайн RESTful и хранилище баз данных.

Контекст: У меня есть ресурс заметок. У пользователей может быть много заметок. Каждая заметка может иметь много тегов.

Функциональные цели: Мне нужно создать маршруты, чтобы сделать следующее:
1) Получить все пользовательские теги. Что-то вроде: GET /users/:id/tags
2) Удалить тег (ы), связанный с запиской.
3) Добавьте тег к определенной заметке.

Цели данных/производительности
1) Получение пользовательских тегов должно быть быстрым. Это делается для "автозагрузки" / "автозаполнения".
2) Предотвратите дубликаты (как можно больше). Я хочу, чтобы теги были повторно использованы как можно больше, чтобы иметь возможность запрашивать данные по тегу. Например, я хотел бы смягчить сценарии, когда пользователь вводит тег, такой как "супергерои", когда тег "супергерой" уже существует.

При этом, как я вижу это, есть два подхода к хранению тегов на ресурсе заметки:

1) в качестве вложенного свойства. Например:

type: 'notes',
attributes: {
  id: '123456789',
  body: '...',
  tags: ['batman', 'superhero'] 
}

2) в качестве собственного ресурса. Например:

type: 'notes',
data: {
  id: '123456789',
  body: '...',
  tags: [1,2,3] // <= Tag IDs instead of strings
}

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

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

Обновление Спасибо за ответы. Одна из самых важных вещей для меня - это определение того, почему использование одного над другим выгодно. Я бы хотел, чтобы в ответ был включен список pro/con.

4b9b3361

Ответ 1

TL;DR

Учитывая ваши требования, IMO вы должны хранить tags в качестве ресурсов, и ваш API должен вернуть notes с тегами в качестве встроенных свойств.


Дизайн базы данных

Держите notes и tags в виде отдельных коллекций (или таблиц). Поскольку у вас много заметок и много тегов, и учитывая тот факт, что основные функции зависят от поиска/автозаполнения на этих tags, это улучшит производительность при поиске notes для конкретного tags. Очень простой дизайн может выглядеть так:

Примечания

{
    'id': 101,    // noteid
    'title': 'Note title',
    'body': 'Some note',
    'tags': ['tag1', 'tag2', ...]
}

теги

{
    'id': 'tag1',    // tagid
    'name': 'batman',
    'description': 'the dark knight',
    'related': ['tagx', 'tagy', ...],
    'notes': [101, 103, ...]
}

Вы можете использовать свойство related для обработки дубликатов путем замены tagx, tagy на аналогичные tags.


Дизайн API

1. Извлечение notes для user:

GET /users/{userid}/notes

Вставить tags в объект notes, когда вы обрабатываете этот маршрут на сервере. Объект notes ваш API-адрес должен выглядеть примерно так:

{
    'id': 101,
    'title': 'Note title',
    'body': 'Some note',
    'tags': ['batman']    // replacing the tag1 by its name from tag collection
}

2. Получение tags для user:

GET /users/{userid}/tags

Если это не требуется, вы можете пропустить отправку свойства notes, которое содержит id для вашего notes.

3. Удаление tags для notes:

DELETE /users/{userid}/{noteid}/{tag}

4. Добавление tags для notes:

PUT /users/{userid}/{noteid}/{tag}

Устраняя проблемы производительности, выборка tags для user должна быть быстрой, потому что у вас есть отдельная коллекция для нее. Кроме того, обработка дубликатов будет проще, потому что вы можете просто добавить аналогичный tags (через id или name) в массив related. Надеюсь, это было полезно.


Почему бы не сохранить теги как вложенные свойства

  • Дизайн не такой масштабируемый, как в предыдущем случае. Если tags - это вложенное свойство, а tag нужно отредактировать или добавить некоторую информацию, тогда для всех notes потребуются изменения, поскольку несколько notes могут содержать один и тот же tag. Принимая во внимание, что сохранение tags в качестве ресурсов, тот же notes будет сопоставлен с их ids, и в коллекции tags/table > будет потребоваться одно изменение.

  • Обработка дубликата tags может быть не такой простой, как сохранение их в качестве отдельных ресурсов.

  • При поиске tags вам нужно будет искать все tags, встроенные в каждый note. Это добавляет накладные расходы.


Единственное преимущество использования tags как вложенного свойства IMO - это упростить добавление или удаление tags для определенного note.

Ответ 2

Это может быть немного сложнее. Поэтому я могу поделиться своим опытом работы с Tag (в нашем случае это была основная функция приложения VoIP).

В любом случае все Tags будут уникальным объектом, который содержит много информации. Как вы знаете, это будет сложнее для передачи, но вам понадобится эта информация, например, ниже. И конечно, Json это самое быстрое решение.

type: 'notes',
data: {
  id: '123456789',
  body: '...',
  tags: [UUID1,UUID2,UUID3] 
}

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

type: 'tag',
data: {
  uuid: '234-se-324',
  body: 'superhero',
  linked: [UUID3, UUID4]
  rate: 4.6,
  usage: 4323
  duplicate: [superheros, suppahero]
}

Как вы можете видеть, мы используем даже дубликаты. Просто сохранить уникальность каждого Tag. Конечно, мы также используем логику для фильтрации корня слов, но, как вы можете видеть из приведенного выше примера, мы также используем дублирующее значение со специальными Roots, такими как "Superhero" и "Suppahero", которые для нас одинаковы.

И вы можете подумать, что это много информации для "autosuggest" или "autocomplete", но мы никогда не сталкивались с проблемами с производительностью (в случае, если разумная поддержка поддержки на стороне). И вся информация важна для каждого использования, и Note в этом случае тоже.

Ответ 3

Сохранение тегов в качестве вложенного свойства имеет смысл, если вы хотите иметь все данные в одной строке. Позвольте мне привести вам пример.

В счет-фактуре вы добавляете элементы,

Название, описание, цена, количество, налог,...

налог в этом случае может быть: НДС 20%, поэтому вы рассчитываете счет-фактуру с 20%, но однодневный налог изменяется до 22%, а все счета-фактуры, которые сохраняются в БД, будут на 2% больше. В этом случае вы добавляете новый столбец, и вы сохраняете его как необработанное число 20, и когда вы читаете этот счет-фактуру из db, вы получаете все данные из одной строки, а не вычисляете их из разных таблиц или переменных.

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

Также есть некоторые другие факторы, которые вы могли бы рассмотреть.

в социальной сети пользователь может иметь теги, которые называются навыками, интересами, спортом и т.д. Нет никакого реального способа отличить теги от (https://github.com/mbleigh/acts-as-taggable-on)

Итак, если вы создаете теги, которые вы отметите многие вещи, вы должны использовать id