1

I am trying out some different options to design and store a document structure in an efficient way in RavenDB.

The structure I am handling user is Session and activity tracking information.

A Session is started when a User logs into the system and the activities start getting created. There could be hundreds activities per session. The session ends when the user closes / logs out.

A factor that complicates the scenario slightly is that the sessions are displayed in a web portal in real time. In other words: I need to keep track of the session and activities and correlate them to be able to find out if they are ongoing (and how long they have been running) or if they are done.

You can also dig around in the history of course.

I did some research and found two relevant questions here on stack overflow but none of them really helped me: Document structure for RavenDB Activity stream design with RavenDb

The two options I have spiked successfully are: (simplified structures)

1:

{
  "User": "User1",
  "Machine": "machinename",
  "StartTime": "2012-02-13T13:11:52.0000000",
  "EndTime": "2012-02-13T13:13:54.0000000",
  "Activities": [
    {
      "Text": "Loaded Function X",
      "StartTime": "2012-02-13T13:12:10.0000000",
      "EndTime": "2012-02-13T13:12:10.0000000"
    },
    {
      "Text": "Executed action Z",
      "StartTime": "2012-02-13T13:12:10.0000000",
      "EndTime": "2012-02-13T13:12:10.0000000"
    }
}

2:

{
  "Session" : "SomeSessionId-1",
  "User": "User1",
  "Machine": "machinename",
  "Text": "Loaded Function X",
  "StartTime": "2012-02-13T13:12:10.0000000",
  "EndTime": "2012-02-13T13:12:10.0000000"
}

{
  "Session" : "SomeSessionId-1",
  "User": "User1",
  "Machine": "machinename",
  "Text": "Executed action Z",
  "StartTime": "2012-02-13T13:12:10.0000000",
  "EndTime": "2012-02-13T13:12:10.0000000"
}

Alternative 1 feels more natural, comming from a relational background and it was really simple to load up a Session, add events and store away. The overhead of loading a Session object and the appending events every time feels really bad for insert performance.

Alternative 2 feels much more efficient, I can simply append events (almost like event-sourcing). But the selections when digging around in events and showing them per session gets a bit more complex.

Is there perhaps a third better alternative? Could the solution be to separate the events and create another read model? Am I overcomplicating the issue?

Community
  • 1
  • 1
Jon
  • 561
  • 4
  • 14
  • Can there be multiple users at the same time creating multiple sessions - activities? – ZVenue Feb 17 '12 at 01:43
  • Yes there can be multiple user at the same time, they will of course only append activities to their own session – Jon Feb 17 '12 at 08:25
  • To be clear: the only reason I keep username and machine is to be able to group / sort by them in the UI – Jon Feb 17 '12 at 08:31

2 Answers2

0

Looks like you just need a User document and a session document. Create two models for "User" and "Session".. session doc would have userid as one property. Session will have nested "activity" properties also. It will be easy to show real time users - sessions - activities in this case. Without knowing more details, I'm over simplifying ofcourse.

EDIT:

//Sample User Document

{
  UserId:"ABC01",
  HomeMachine:"xxxx",
  DateCreated:"12/12/2011"
}


//Sample Session Document

{
  UserId:"ABC01",
  Activities
    {
      Activity 1 properties
    }
    {
      Activity 2 properties
    }
    ...
    ...
    etc..

}
ZVenue
  • 4,967
  • 16
  • 61
  • 92
  • So this is my option 1 but with the user pulled out as its own document? – Jon Feb 17 '12 at 08:27
  • Keeping individual session and all related activities in one document makes sense if you need to display session and activities within a session. And relate all such session documents to a single user document that's logged in. – ZVenue Feb 17 '12 at 17:40
  • I see what you mean. I am leaning towards a document for the session containing the user, machine and session details. And an activity document referencing the session. – Jon Feb 17 '12 at 21:15
  • I'm sure you thought about - activity documents growing exponentially as each session can result in 100s of activities in this case. – ZVenue Feb 18 '12 at 00:11
0

I definitely think you should go with some variant of option 2. Won't the documents grow very large in option 1? That would probably make the inserts very slow. I can't really see why showing events per session would be any more complicated in option 2 than in option 1, you can just select events by session with

session.Query<Event>().Where(x => x.Session == sessionId)

and RavenDB will automatically create an index for it. And if you want to make more complicated queries you could always create more specialized indexes for that.

Johan Driessen
  • 841
  • 2
  • 8
  • 13
  • I like this solution too. The issue I have is showing active Sessions using that structure. Perhaps a hybrid is best - a Session document and then dump events in a pile using a simple id reference – Jon Feb 17 '12 at 21:10