Может ли graph db решить мои проблемы с графом?
У меня есть данные транзакций (pastebin.com/ZswbyVHM), например:
{"accountId":3,"recordedAt":"2013-12-01T00:00:00.000Z","region":"South","status":"H"}
{"accountId":3,"recordedAt":"2014-01-01T00:00:00.000Z","region":"South","status":"A"}
{"accountId":3,"recordedAt":"2014-02-01T00:00:00.000Z","region":"South","status":"B"}
{"accountId":3,"recordedAt":"2014-03-01T00:00:00.000Z","region":"South","status":"E"}
{"accountId":3,"recordedAt":"2014-04-01T00:00:00.000Z","region":"South","status":"C"}
когда групповые транзакции по accountId
это можно рассматривать как:
{"accountId": 3, "region":"South", "transactions": [
{"recordedAt":"2013-12-01T00:00:00.000Z", "status": "H"},
{"recordedAt":"2014-01-01T00:00:00.000Z", "status": "A"},
{"recordedAt":"2014-02-01T00:00:00.000Z", "status": "B"}]
}
Исходя из вышесказанного, я хотел бы создать график отношения статуса из коллекции транзакций, который может сохранить порядок статуса, recordedAt
, accountId
со следующими свойствами:
- Узлы графика представляют статус и неявно порядок статуса.
Их края имеют
accounts
массив accountId, имеющий одинаковый статус, изменяющийся от одного к другому в том же порядке.Путь графа является пересечением между
accountId
,status
а такжеlevel
(порядок статуса).
Пример: график отношения статуса
Есть два состояния от корня "A" и "H".
На уровне 0,
AccountId 1, 2, 4 имеют такой же статус "A", кроме AccountId 3.
Путь AccountId 4 заканчивается на этом уровне.
На уровне 1,
AccountId 1, 2 имеют одинаковый статус "A",
AccountId 3 имеет тот же статус "A", но с другого пути.
Путь AccountId 1 заканчивается на этом уровне.
На уровне 2
AccountId 2 имеет статус "B".
AccountId 3 имеет тот же статус "B", но с другого пути.
На уровне 3
AccountId 2 имеет статус "A", а AccountId 3 имеет статус "E"
Итак, я разработал 3 крайние коллекции:
Дизайн 1: Каждое ребро представляет собой отношение между вершиной состояния, которая использует level
сохранить порядок транзакции.
{"_from": "status/root", "_to": "status/A", "level": 0, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-05-01"}]}
{"_from": "status/A" , "_to": "status/A", "level": 1, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-06-01"}]}
{"_from": "status/A" , "_to": "status/B", "level": 2, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-07-01"}]}
{"_from": "status/B" , "_to": "status/A", "level": 3, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-08-01"}]}
{"_from": "status/A" , "_to": "status/G", "level": 4, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-09-01"}]}
{"_from": "status/G" , "_to": "status/G", "level": 5, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-10-01"}]}
{"_from": "status/G" , "_to": "status/H", "level": 6, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-11-01"}]}
{"_from": "status/H" , "_to": "status/D", "level": 7, "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-12-01"}]}
{"_from": "status/D" , "_to": "status/A", "level": 8, "accounts": [{"id": 2, "region": "South", "recordedAt": "2013-01-01"}]}
{"_from": "status/A" , "_to": "status/A", "level": 9, "accounts": [{"id": 2, "region": "South", "recordedAt": "2013-02-01"}]}
Дизайн 2: Каждое ребро - это отношение между вершиной уровня, которая имеет атрибут ребра status
,
{"_from": "level/root", "_to": "level/0", "status": "A", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-05-01"}]}
{"_from": "level/0" , "_to": "level/1", "status": "A", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-06-01"}]}
{"_from": "level/1" , "_to": "level/2", "status": "B", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-07-01"}]}
{"_from": "level/2" , "_to": "level/3", "status": "A", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-08-01"}]}
{"_from": "level/3" , "_to": "level/4", "status": "G", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-09-01"}]}
{"_from": "level/4" , "_to": "level/5", "status": "G", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-10-01"}]}
{"_from": "level/5" , "_to": "level/6", "status": "H", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-11-01"}]}
{"_from": "level/6" , "_to": "level/7", "status": "D", "accounts": [{"id": 2, "region": "South", "recordedAt": "2012-12-01"}]}
{"_from": "level/7" , "_to": "level/8", "status": "A", "accounts": [{"id": 2, "region": "South", "recordedAt": "2013-01-01"}]}
{"_from": "level/8" , "_to": "level/9", "status": "A", "accounts": [{"id": 2, "region": "South", "recordedAt": "2013-02-01"}]}
Дизайн 3: путем добавления виртуальной вершины (регион, год).
Эту конструкцию пытаются устранить accounts
чтобы избежать фильтрации массива объектов. Проще фильтровать по атрибуту ребра.
{"_from": "level/root" , "_to": "level/South"}
{"_from": "level/South", "_to": "level/2012"}
{"_from": "level/2016" , "_to": "level/0", "status": "A", "accountId": 1}
{"_from": "level/2012" , "_to": "level/0", "status": "A", "accountId": 2}
{"_from": "level/2017" , "_to": "level/0", "status": "A", "accountId": 4}
{"_from": "level/0" , "_to": "level/1", "status": "A", "accountId": 1}
{"_from": "level/0" , "_to": "level/1", "status": "A", "accountId": 2}
{"_from": "level/1" , "_to": "level/2", "status": "B", "accountId": 2}
{"_from": "level/2" , "_to": "level/3", "status": "A", "accountId": 2}
{"_from": "level/3" , "_to": "level/4", "status": "G", "accountId": 2}
{"_from": "level/4" , "_to": "level/5", "status": "G", "accountId": 2}
{"_from": "level/5" , "_to": "level/6", "status": "H", "accountId": 2}
{"_from": "level/6" , "_to": "level/7", "status": "D", "accountId": 2}
{"_from": "level/7" , "_to": "level/8", "status": "A", "accountId": 2}
{"_from": "level/8" , "_to": "level/9", "status": "A", "accountId": 2}
- Этот график использует для запроса:
- Напомним шаблон состояния для конкретного
accountId
путем фильтрации пути, чтобы все ребра указали идентификатор.
- Напомним шаблон состояния для конкретного
Псевдо AQL:
FOR v, e, p IN 1..20 OUTBOUND status/root statusRelations
FILTER p.edges[*].accountId ALL == id
RETURN p.edges.status
- Какие статусы приводят к интересному статусу (по региону или году)?
Псевдо AQL:
FILTER e._to == "status/D" (AND e.region == "North" AND e.year == 2013)
RETURN SLICE(p.edges[*], -3) // RETURN 3 previous statuses that followed by "D"
- Какой статус больше всего произошел за год?
Псевдо AQL:
FILTER e.year == 2013
COLLECT status = e.status WITH COUNT INTO length
RETURN status
Какой из моих дизайнов лучше всего подходит для ArangoDB и может отвечать на мои вопросы?