Целостность данных в JSON (B) при замене EAV - PullRequest
1 голос
/ 05 октября 2019

Я реализую базу данных для нового приложения и рассматриваю возможность использования полей JSON вместо традиционного EAV подхода. Все вроде бы хорошо, но есть одна большая проблема , которую я не знаю, как решить.

Например;в традиционной модели EAV у нас было бы три табеля;

  • Первая таблица для хранения атрибутов
  • Вторая таблица для хранения значений
  • Третья таблица для связывания этих двух элементов.

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

Теперь введите JSON. Насколько я понимаю, весь смысл замены EAV на JSON заключается в сохранении всех значений в самих полях. Таким образом, наша запись может выглядеть следующим образом.

{
   "color": "Blue",
   "size": "Large"
}

вместо сохранения значений по первичным ключам.

Поэтому мой вопрос, если я в будущем поменяю название цвета сскажем Blue до Purple, как мне справиться с целостностью данных? Поскольку в классической модели EAV первичные ключи не изменятся.

Я использую базу данных Postgresql с Django.

Ответы [ 2 ]

2 голосов
/ 05 октября 2019

Используя Django ORM, единственный способ манипулировать значениями полей JSON - это перебирать модели. Но вы можете запросить / отфильтровать отдельные поля:

Предположим, у вас есть эта модель:

from django.contrib.postgres.fields import JSONField
from django.db import models

class Thing(models.Model):
    attributes = JSONField()

У вас должна быть возможность запрашивать синие вещи (см. Запрос JSONField ):

blue_things = Thing.objects.filter(attributes__color='Blue')

Теперь вы можете перебирать эти экземпляры модели и обновлять значение:

for thing in blue_things:
    thing.attributes['color'] = 'Purple'
    thing.save()

Возможно, вы захотите сделать это в транзакции.

PostgreSQL позволяет вам напрямую манипулировать полями JSONB:

UPDATE appname_thing SET attributes = attributes || '{"color": "Purple"}' WHERE attributes->>'color' = 'Blue';

Насколько я знаю, в настоящее время это не поддерживается Django, поэтому вам придется выполнить необработанный запрос .

1 голос
/ 05 октября 2019

Я лично не знаком с Django, но если вы хотите воспользоваться функциональностью JSON в PostgreSQL, я бы, вероятно, использовал столбец первичного ключа отдельно от вашего более произвольного JSON. Что-то вроде:

CREATE TABLE stuff (
    id SERIAL NOT NULL PRIMARY KEY,
    data JSON NOT NULL
);

Таким образом, вы получаете столбец id в качестве надежного справочника и можете делать с JSON все, что захотите. Если у вас есть известная / предсказуемая структура JSON, вы можете создать индексы , чтобы повысить производительность при запросе в данных JSON.

Оригинальный ответ:

Мне не ясно, какой продукт базы данных вы собираетесь использовать, но, будучи знакомым с MongoDB, базой данных, ориентированной на документы JSON, я могу рассказать вам, как она там работает. Когда вы вставляете документ, если вы его не предоставите, добавляется поле _id, которое MongoDB называет ObjectId. Таким образом, если вы вставите пример JSON, у вас будет что-то вроде:

{
   "_id": ObjectId("5d97d46a54198e0797d86457"),
   "color": "Blue",
   "size": "Large"
}

Если вы хотите обновить только этот документ, вы можете использовать _id в «предложении where», например:

db.collection.updateOne({
   _id: ObjectId("5d97d46a54198e0797d86457")
}, {
    $set: {
        color: "Red",
        size: "Medium"
    }
});

Опять же, не зная, какую БД вы используете, это может быть далеко от базы. Если вы имеете дело с JSONB в чем-то вроде PostgreSQL, то вы обычно включаете serial или аналогичный столбец для поддержания фиксированного первичного хранения, как вы упомянули.

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