Reputation: 3526
Let's imagine I have three classes: User
,Post
, Comment
. Standard actions — user can create posts and write comments to these posts. So we have the situation depicted below:
I need to perform these three queries very quickly:
And it looks like it isn't possible even if I will use partitioning. At least not with a single reliable dictionary. Probably I need several dictionaries for different queries. Am I correct?
Upvotes: 2
Views: 315
Reputation: 256
I'm working on the same thing! First of all: My schema is a bit different. I have a user, a topic and a comment. The topic is just a class with a list of comment ids(IEnumerable long), nothing more. The first comment is the post.
Oh, really first of all, little warning: I'm just beginning with Service Fabric, so I might be doing it wrong ;)
The user is not relevant for me. I just store the userid on the comment. When retrieving a list of comments I get the users from the stateful users service. Or I will store the users name in the comment directly, not sure yet.
So that leaves me with topics and comments. First I thought 'lets create a Stateful TopicService and a Stateful CommentService'. But then I realised that for every topic I load I need to call the CommentService for each comment to get the comments.
So I created a TopicService which handles 2 IReliableDictionaries: topics and comments.
Whenever a comment is posted I use the TopicId as the partitionkey and in that partition the comment is stored. So NOT using the commentid !! This way all the comments for a specific topic are in the same partition.
When loading a topic with all the comments I use the TopicId as the partitionkey again, get the topic from the reliabledictionary for the topics and loop the list of comment ids in the reliabledictionary for the comments. Not sure if it helps, but my GetComments looks like this:
var topics = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, TopicModel>>("topics");
var comments = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, CommentModel>>("comments");
List<CommentModel> result = new List<CommentModel>();
using (var tx = this.StateManager.CreateTransaction())
{
ConditionalValue<TopicModel> topic = await topics.TryGetValueAsync(tx, topicid);
if(topic.HasValue)
{
foreach(long commentid in topic.Value.CommentsInternal)
{
ConditionalValue<CommentModel> comment = await comments.TryGetValueAsync(tx, commentid);
if (comment.HasValue)
result.Add(comment.Value);
}
}
await tx.CommitAsync();
}
return result;
I'm not done yet, the method some more work.
Perhaps this helps you :)
edit: ow, there is a disadvantage! When you want to load a single comment by its id, you need to provide the topicid. So my CommentModel class has a CommentId and a TopicId property.
Upvotes: 2