Client UI Audit

Hi,
Which would it be the best approach to audit all the client interactions (react app) in the graphs?

a) have a node or relationships with dates and down there with the sessionId have all the actions (login, search, create, logout) i guess nodes but in the same level
b) or have nodes that have relationships between them which will define the flow of interaction

I started few weeks ago with neo4j and my knowledge is quite poor...

Would appreciate some read :slight_smile:

Thanks!

Hi @undefined21 ,

The general rule-of-thumb for data modeling applies equally well to graphs: model the data so that it is easy and efficient to answer questions. What questions do you want to ask that the data can answer?

A good way to start is by literally sketching a representative sample of the graph on paper, then trying to answer questions by tracing patterns in the data. This may sound awkward at first but when you try it you'll realize that you probably already have a natural way to think about the graph that can provide meaningful answers.

Anything you can answer on paper will be translate well into a Cypher query.

Try it, then share the sketches here if you get stuck.

Best,
ABK

Hi thanks for the response!

After some read, this is what I get as a first sketch,

With that graph I could achieve mainly everything that I want, get all user events in each session or group by user.

But what about if we want to get the sessions in some timeframe, for example: Get which users have access to the system on 1st of May. Do you think that design would perform ok or would it be expensive that operation because we have to check in each session node the timestamp? Other way to do it, it would be to add as a relation type the whole date (01_05_2021) but in that case, how we could get the session between two dates? Could we make a query in cypher with that conditions?

Thanks for your time!

:wink: :smiley:

You could query the sessions with a predicate that sets boundaries on the timestamp for the timeframe you want. And you should then index that property. That should perform adequately.

See here for an example of a range query: WHERE - Neo4j Cypher Manual

Adding date nodes, as you propose, is an alternative. You might then want to link the date nodes themselves to easily traverse :PREVIOUS or :NEXT dates. That effectively creates an "in-graph index". Querying is less obvious. One advantage is that the patterns and coincidence of events become easier to see.

Search around for "Neo4j time tree" to find examples. For instance Generate a time tree in Cypher to model dates | Graph*space

Best,
ABK

Thanks @abk! That's a nice response, lot of content there...

The first approach seems easier but we have to add the index which I do not know how it could affect the memory and performance perspective in Neo4j (I need to read about the pros & cons hahah).

I think, I like more the second approach as you say because is more visual and it is quite easy if you want to find the exact day logs. But the only problem that I see is (maybe because I do not still dig enough in cypher queries), what about the user that does not log in two days (2-3) in the application? We could not apply the query of unit steps right?

Imagine the user logs in the application 2021-may-01, 2021-may-04, 2021-may-05, ...

And our query would be get logs from 1st of may to 3rd of may

MATCH p = (y:Year {year: 2021})-[:HAS_MONTH]->(m:Month {month: 5})-[:HAS_DAY]->(:Day {day: 1})-[:NEXT*0..3]->(day)

So if we apply that cypher query, in our example, it would give 1-4-5 days and it would return a wrong answer. Is there any query that we could apply to do that search just using the relationships or do we have to do as the first case using the WHERE clause?

Thanks for your time
:compass: :green_book:

The 'Audit' node has no connection to Year, month, day nodes. 'Profile' only has the connections per your screenshot. Try this:

MATCH (a:Audit)-[rel:HAS_AUDIT]->(u:Profile { uuid: "xxxxxxxxx" })

MATCH 
  (u)-[:HAS_YEAR]->(:Year {year: 2021})-[:HAS_MONTH]->(m:Month {month: 5})
  -[:HAS_DAY]->(d:Day)-[:ACTIVITY_AT]->(s1:Session)-[:NEXT]->(s2:Session)
  
where 20 <= d.day <= 28

RETURN s1, s2

That query works! I was obvious (after see it) to use where clause, thanks for your time