Hi Jérémy,
there are several conceptional approaches you could follow for your use case.
I will try to explain all of them and give some hints on their pros & cons:
1) Create one edge per contact:
* Simply store a new edge (_from, _to, details) for edge contact.
+ Will be fastest write performance.
+ You do not have to take care of writing conflicts if several instances are storing these edges.
+ You can directly see how many calls a person has made in total (to any other person) (Length of connected edges)
- Edge collection grows rather fast
- You have to write an AQL Filter to find all contacts between person A and B.
2) Create one edge per person-pair:
* Store one (directed) edge per person pair and add a counter and all other relevant values.
+ Stored amount of data is minimal
+ You can directly see how many other persons one person has contacted (Length of connected edges)
+ You can directly see how many contacts a person has to a specific other person on one edge.
+ Graph-queries should perform faster as their runtime is typically bound by the amount of edges per vertex.
- Requires a transaction for each write
- Reduces write performance in case of many concurrent writers.
I would always prefer version 2) above version 1) except one specific case, you have a large amount of concurrent writers of edges.
To update the edge you can for example use the AQL statement:
FOR contact in in_contact
FILTER contact._from == @from AND contact._to @to
LET oldCount = contact.count
LET dates = contact.dates
UPDATE contact WITH {count: oldCount + 1, dates: UNION(dates, [@newDate]) } in in_contact
and replace the bindVars @from, @to, @newDate accordingly.
This will then be transactional and can be used concurrently.
hope that helps
best
Michael