Моделирование данных объекта с атрибутами - PullRequest
2 голосов
/ 03 июня 2010

Я храню некоторую основную информацию, «источники данных», поступающую в мое приложение. Эти источники данных могут быть в форме документа (например, PDF и т. Д.), Аудио (например, MP3 и т. Д.) Или видео (например, AVI и т. Д.). Скажем, например, меня интересует только имя файла источника данных. Итак, у меня есть следующая таблица:

DataSource
Id (PK)
Filename

Для каждого источника данных мне также нужно хранить некоторые его атрибуты. Примером для PDF будет «количество страниц». Примером для аудио будет «битрейт». Примером для видео будет «продолжительность». Каждый источник данных будет иметь различные требования к атрибутам, которые должны быть сохранены. Итак, я смоделировал «атрибут источника данных» следующим образом:

DataSourceAttribute
Id (PK)
DataSourceId (FK)
Name
Value

Таким образом, у меня были бы такие записи:

DataSource->Id = 1
DataSource->Filename = 'mydoc.pdf'

DataSource->Id = 2
DataSource->Filename = 'mysong.mp3'

DataSource->Id = 3
DataSource->Filename = 'myvideo.avi'

DataSourceAttribute->Id = 1
DataSourceAttribute->DataSourceId = 1
DataSourceAttribute->Name = 'TotalPages'
DataSourceAttribute->Value = '10'

DataSourceAttribute->Id = 2
DataSourceAttribute->DataSourceId = 2
DataSourceAttribute->Name = 'BitRate'
DataSourceAttribute->Value '16'

DataSourceAttribute->Id = 3
DataSourceAttribute->DataSourceId = 3
DataSourceAttribute->Name = 'Duration'
DataSourceAttribute->Value = '1:32'

Моя проблема в том, что это не масштабируется. Например, скажем, мне нужно запросить все документы PDF вместе с общим количеством страниц:

Filename, TotalPages
'mydoc.pdf',  '10'
'myotherdoc.pdf', '23'
...

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

Ответы [ 3 ]

0 голосов
/ 03 июня 2010

Это может сработать, но определить слишком дорого ...

select 
datasource.id, 
d1.id as d1id, 
d1.value as d1filename,
d2.id as d2id,
d2.value as d2totalpages

 from datasource 
inner join datasourceattribute d1
on datasource.id = d1.datasourceid and d1.name = 'filename'
inner join datasourceattribute d2
on datasource.id = d2.datasourceid and d2.name = 'totalpages'
having d1filename like '%pdf'
0 голосов
/ 03 июня 2010

Масштабирование является одной из наиболее распространенных проблем со структурами данных EAV (Entity-Attribute-Value). Короче говоря, вам нужно запросить метаданные (то есть найти атрибуты), чтобы получить к ним данные. Однако вот запрос, который вы можете использовать для получения нужных вам данных:

Select DataSourceId 
    , Min( Case When Name = 'TotalPages' Then Value End ) As TotalPages
    , Min( Case When Name = 'BitRate' Then Value End ) As BitRate
    , Min( Case When Name = 'Duration' Then Vlaue End ) As Duration
From DataSourceAttribute
Group By DataSourceId 

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

Select DataSource.FileName
    , Min( Case When DataSourceAttribute.Name = 'TotalPages' Then Value End ) As TotalPages
    , Min( Case When DataSourceAttribute.Name = 'BitRate' Then Value End ) As BitRate
    , Min( Case When DataSourceAttribute.Name = 'Duration' Then Vlaue End ) As Duration
From DataSourceAttribute
    Join DataSource
        On DataSource.Id = DataSourceAttribute.DataSourceId
Group By DataSource.FileName
0 голосов
/ 03 июня 2010

Кажется, что вы хотите чего-то немного большего, чем типичный реляционный дБ. Звучит как хороший кандидат на что-то вроде Lucene или MongoDB . Lucene - это механизм индексирования, который позволяет хранить и индексировать любые типы документов. MongoDB находится в середине между СУБД и хранилищем документов в свободной форме. JSON в той или иной форме (хорошим примером может служить MongoDB).

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