Data Model - moevm/nosql2h20-relatives-neo4j GitHub Wiki
1. Person - сущность представляющая собой конкретного человека, имеет следующие атрибуты:
id
: Int - уникальный идентификатор, генерируется neo4j
firstName
: str - Имя человека
lastName
: str - Фамилия человека -
middleName
: str - Отчество человека
sex
: str - Пол
educ
: str - Образование
bornDate
: Date - Дата рождения
socialStatus
: str - Пару слов о себе
img
- Фотография человека (Путь на диске или URL)
2. RelativeRealtions - родословное отношение между людьми, имеет следующие атрибуты:
Id
: Int - уникальный идентификатор, генерируется neo4j
PersonIdOne
: Int - идентификатор первого человека в отношении
PersonIdTwo
: Int - идентификатор второго человека в отношении
Каждый человек в генеалогическом дереве представляет собой отдельный узел с указанными на графф - диаграмме атрибутами.
Идентификатор узла - уникальный идентификатор человека. Он используется для создания родословных отношений
между узлами, членами семьи. Каждое семейное дерево имеет свою метку на узлах label
- например Давыдовы
.
Это позволяет проще строить поисковые запросы и создавать отношения. Само же отношение так же имеет метку label
,
означающая тип отношения. В данный момент существует только один тип отношений - DirectRelative
1. Node:
id
- 4B
firstName
: str - 50B
lastName
: str - 50B
middleName
: str - 50B
bornDate
: Date - 4B
sex
: str - 50B
educ
: str - 50B
socialStatus
: str - 100B
label
- 50B
img
- 200B
Sum: 508B
2. Relation
id
- 4B
label
- 50B
Sum: 54B
Пусть в дереве N узлов, M отношений => v = 508N + 54M
Для дерева высотой 4, мы будем иметь 13 узлов и 14 связей. Примем эти числа как средние значения для каждого дерева => M = 13/14*N
Тогда v = 508N + 5413/14N = 558.14N
Примем N = 13, M = 14(Случай дерева до прадедушек и прабабушек 1 из членов нашей команды) -> v = 7360B
Пусть в базе данных 1000 генеалогических деревьев => V = 7360000B = 7,02Mb фактического объема
Исключая переменные id
из узла и отношения, мы получим формулу для чистого объема => v = 504N + 5013/14N = 550,42N
Избыточность модели Neo4j: 558.14N/550,42N
Фактический
Добавление узла
CREATE (n:FamilyTree {firstName: "Alex", lastName: "Davydov", middleName: "Anatolyevich",
bornDate: datetime("1999-09-12"), socialStatus: "student"})
SET n.id = id(n)
Удаление узла
MATCH (n:FamilyTree { id: $id1 })
DELETE n
Добавление связи
MATCH (a:FamilyTree), (b:FamilyTree)
WHERE a.id = $id1 AND b.id = $id2
CREATE (a)-[: DirectRelative]->(b)
Удаление связи
MATCH (n:FamilyTree {id: $id1})-[r: DirectRelative]-(m:FamilyTree {id: $id2})
DELETE r
_1. Person
id
: Int - 4B
firstName
: str - 50B
lastName
: str - 50B
middleName
: str - 50B
bornDate
: Date - 4B
socialStatus
: str - 100B
img
- 200B
Sum: 458B
_2. RelativeRealtions
Id
: Int - 4B
PersonIdOne
: Int - 4B
PersonIdTwo
: Int - 4B
Sum: 12B
Пусть мы имеем N людей и M отношений родословной связи между ними => v = 458N + 12M
Для дерева высотой 4, мы будем иметь 13 узлов и 14 связей. Примем эти числа как средние значения для каждого дерева => M = 13/14*N
Тогда v = 458N + 1213/14 = 469,14*N
(как и в случае с Neo4j) -> v = 6098B
Пусть в базе данных 1000 генеалогических деревьев => V = 6098000B = 5,82Mb фактического объема
Исключая переменные Id
, PersonIdOne
, PersonIdTwo
пересчитаем формулу => v = 454*N
Избыточность модели SQL: 469,14N/454N
Добавить нового человека
INSERT INTO Person
VALUE (person_id, "Alex", "Davydov", "Anatolyevich", "1999-09-12", "student")
Добавить новую родственную связь между людьми
INSERT INTO RelativeRelations
VALUE (relation_id, person_id_1, person_id_2)
Запросы на Cipher являются более компактными по сравнению на SQL. Для реализации отношения в SQL требуется созданиe дополнительных сущностей
Графовая модель данных занимает больше места в памяти, чем реляционная, но работает быстрее.
Вывод - neo4j подходит лучше, для предметной области генеалогические деревья
{
"_id": <ObjectId>,
"firstName": "Alexander",
"lastName": "Davydov",
"middleName": "Anatolyevich",
"bornDate": <Timestamp>,
"socialStatus": "student",
"img": "/Home/imgs/img.jpg",
"fatherId": <ObjectId>,
"motherId": <ObjectId>
}
Каждое поле за исключением fatherId
, motherId
представляет собой ту же сущность как и в обзоре SQL-сущностей(см. первые пункты статьи)
fatherId
- это идентификатор отца, по умолчанию имеет значение null
motherId
- это идентификатор матери, по умолчанию имеет значение null
id
: Int - 4B
firstName
: String - 50B
lastName
: String - 50B
middleName
: String - 50B
bornDate
: Date - 4B
socialStatus
: String - 100B
img
: String - 200B
fatherId
: Int - 4B
motherId
: Int - 4B
Sum: 466B
Мы получаем довольно таки простой случай, где объем информации будет пропорционален числу сущностей в дереве => v = 466*N
Пусть мы имеем 1000 деревьев в среднем включающих 14 родственников => V = 144661000 = 6,22Mb фактического объема данных
Исключая переменные _id
, motherId
, fatherId
, получаем формулу для пересчета чистого объема данных => v = 454*N
Избыточность модели Mongo: 466N/454N
Добавление узла
db.familyTree.insertOne(
{
_id:1,
firstName: "Alexander",
lastName: "Davydov",
middleName: "Anatolyevich",
bornDate: new Date("1999-09-12"),
socialStatus: "student",
img: "/Home/imgs/img.jpg",
fatherId: null,
motherId: null
})
Добавление связи между узлами
db.users.updateOne(
{
_id: $id
},
{
$set: {`fatherId` : $fatherId, `motherId`: $motherId}
})