当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Redis key partitioning practices with linked items

问题描述:

I'm using a Redis database and ServiceStack client for it. I have a class called "Post" which has a property GroupId. Now when I'm storing this class the key is "urn:post:2:groupid:123". Now if I want to find all posts related to one group i need to use SearchKeys("urn:*groupid:123") method to retrieve all posts related to one group. Is this best practice to use Redis DB or should I convert my post key into form of "urn:groupid:123"post:2" ? If so how I can achieve this?

Post class:

 public class Post

{

public const string POST_INCREMENT_KEY = "POST_INCREMENT";

public string Id { get; set; }

public string Message { get; set; }

public string GroupId { get; set; }

public void BuildId(long uniqueId)

{

Id = uniqueId + ":groupid:" + GroupId;

}

}

Code for storing post:

var post = new Post

{

GroupId = groupId,

Message = Request.Form["message"]

};

post.BuildId(_client.Increment(Post.POST_INCREMENT_KEY, 1));

_client.Store(post);

网友答案:

The best practice in redis is to maintain an index of the relationship you want to query.

Manually maintaining an index in Redis

An index is just a redis SET containing the related Ids you want to maintain, given that you want to "retrieve all posts related to one group" I would maintain the following index:

const string GroupPostIndex = "idx:group>post:{0}";

So that everytime you store a post, you also want to update the index, e.g:

client.Store(post);
client.AddItemToSet(GroupPostIndex.Fmt(groupId), post.Id);

Note: Redis SET operations are idempotent in that adding an item/id multiple times to a SET will always result in there being only one occurrence of that item in the SET, so its always safe to add an item to the set whenever storing a POST without needing to check if it already exists.

Now when I want to retrieve all posts in a group I just need to get all the ids from the SET with:

var postIds = client.GetAllItemsFromSet(GroupPostIndex.Fmt(groupId));

Then fetch all the posts with those ids:

var posts = redis.As<Post>().GetByIds(postIds);

Using ServiceStack.Redis Related Entities API's

The above shows what's required to maintain an index in Redis yourself, but as this is a common use-case, ServiceStack.Redis also offers a high-level typed API that you can use instead.

Which lets you store related entities with:

client.As<Group>().StoreRelatedEntities(groupId, post);

Note: this also takes care of storing the Post

and retrieve them with:

var posts = client.As<Group>().GetRelatedEntities<Post>(groupId);

It also offers other convenience API's like quickly finding out how many posts there are within a given group:

var postsCount = client.As<Group>().GetRelatedEntitiesCount<Post>(groupId);

and deleting either 1 or all entities in the group:

client.As<Group>().DeleteRelatedEntity<Post>(groupId, postId);
client.As<Group>().DeleteRelatedEntities<Post>(groupId); //all group posts
分享给朋友:
您可能感兴趣的文章:
随机阅读: