.NET中使用Redis (二)
很久以前寫了一篇文章 .NET中使用Redis 介紹了如何安裝Redis服務端,以及如何在.NET中調用Redis讀取數據。本文簡單介紹如何設計NoSQL數據庫,以及如何使用Redis來存儲對象。
和傳統的關系型數據庫不同,NoSQL大部分都是以鍵值對存儲在內存中的,我們不能直接把RDBMS里面的一些做法直接移植到NoSQL中來,一個 最主要的原因是,在NoSQL中缺少RDBMS中的一些諸如join ,union以及一些在關系型數據庫中效率很高的執行語句,這些在NoSQL不能很好的支持,或者說效率低。
下文首先通過例子介紹在SQLServer中設計一個DB系統以及與NoSQL環境中設計一個DB的區別,最后演示如何在Redis中對數據進行讀寫操作。
一個簡單的博客系統
假設我們要設計一個簡單的博客系統,用戶可以注冊一個博客(Blog),然后可以在上面寫文章(Post),文章可以分類(Category)以及添加標簽(Tag),用戶可以對文章進行評論(Comment)。
在該系統中,我們需要實現,如下基本功能:
- 首頁:顯示所有人的博客
- 首頁:顯示最近的所有發表的文章
- 首頁:顯示所有的最近的評論
- 首頁:顯示博客的標簽云
- 首頁:顯示所有的分類
- 文章頁面:顯示文章以及所有的評論
- 文章頁面:添加評論
- 標簽頁面:顯示所有標簽以及標簽對應的文章
- 分類頁面:顯示所有分類以及分類對應的文章 </ul>
如果在SQLServer中,相信很簡單就可以設計出這樣一個DB了。
在NoSQL環境中,我們不能直接將上面的結構搬進來,所以需要根據需求重新設計我們的模型。
定義實體
在NoSQL環境下,所有的數據其實都是以key和value的形式存儲在內存中的,value通常是序列化為字符串保存的。我們使用redis客戶端的時候,可以直接將對象存儲,這些客戶端在內部實現上幫助我們進行了序列化。所以第一步就是需要定義實體模型:
首先來看User實體:
public class User{ public User() { this.BlogIds = new List<long>(); }</span><span style="color:blue;">public long </span><span style="color:black;">Id { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public string </span><span style="color:black;">Name { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">long</span><span style="color:black;">> BlogIds { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; }
}</span></pre>
User實體中,包含了用戶的Id,Name以及博客的Id。
然后Blog實體:
public class Blog{ public Blog() { this.Tags = new List<string>(); this.BlogPostIds = new List<long>(); }</span><span style="color:blue;">public long </span><span style="color:black;">Id { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public long </span><span style="color:black;">UserId { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public string </span><span style="color:black;">UserName { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> Tags { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">long</span><span style="color:black;">> BlogPostIds { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; }
}</span></pre>
包含了標簽Tag,以及文章Id列表。
文章BolgPost實體:
public class BlogPost{ public BlogPost() { this.Categories = new List<string>(); this.Tags = new List<string>(); this.Comments = new List<BlogPostComment>(); }</span><span style="color:blue;">public long </span><span style="color:black;">Id { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public long </span><span style="color:black;">BlogId { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public string </span><span style="color:black;">Title { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public string </span><span style="color:black;">Content { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> Categories { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> Tags { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; } </span><span style="color:blue;">public </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPostComment</span><span style="color:black;">> Comments { </span><span style="color:blue;">get</span><span style="color:black;">; </span><span style="color:blue;">set</span><span style="color:black;">; }
}</span></pre>
包含了一篇文章的基本信息,如文章分類,文章標簽,文章的評論。
最后看評論BlogPostComment實體:
public class BlogPostComment{ public string Content { get; set; } public DateTime CreatedDate { get; set; } }具體實現
實體定義好了之后,我們就可以開始具體實現了。為了演示,這里通過單元測試的方式實現具體功能:
首先要把Redis的服務端啟動起來,然后在工程中新建一個Redis客戶端,之后的所有操作都通過這個客戶端進行。
[TestFixture, Explicit, Category("Integration")]public class BlogPostExample{ readonly RedisClient redis = new RedisClient("localhost");[</span><span style="color:#2b91af;">SetUp</span><span style="color:black;">] </span><span style="color:blue;">public void </span><span style="color:black;">OnBeforeEachTest() { redis.FlushAll(); InsertTestData(); }
}</span></pre>
在單元測試的SetUp中,我們插入一些模擬數據,插入數據的方法為InsetTestData方法:
public void InsertTestData() { var redisUsers = redis.As<User>(); var redisBlogs = redis.As<Blog>(); var redisBlogPosts = redis.As<BlogPost>();</span><span style="color:blue;">var </span><span style="color:black;">yangUser = </span><span style="color:blue;">new </span><span style="color:#2b91af;">User </span><span style="color:black;">{ Id = redisUsers.GetNextSequence(), Name = </span><span style="color:#a31515;">"Eric Yang" </span><span style="color:black;">}; </span><span style="color:blue;">var </span><span style="color:black;">zhangUser = </span><span style="color:blue;">new </span><span style="color:#2b91af;">User </span><span style="color:black;">{ Id = redisUsers.GetNextSequence(), Name = </span><span style="color:#a31515;">"Fish Zhang" </span><span style="color:black;">}; </span><span style="color:blue;">var </span><span style="color:black;">yangBlog = </span><span style="color:blue;">new </span><span style="color:#2b91af;">Blog </span><span style="color:black;">{ Id = redisBlogs.GetNextSequence(), UserId = yangUser.Id, UserName = yangUser.Name, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"Architecture"</span><span style="color:black;">, </span><span style="color:#a31515;">".NET"</span><span style="color:black;">, </span><span style="color:#a31515;">"Databases" </span><span style="color:black;">}, }; </span><span style="color:blue;">var </span><span style="color:black;">zhangBlog = </span><span style="color:blue;">new </span><span style="color:#2b91af;">Blog </span><span style="color:black;">{ Id = redisBlogs.GetNextSequence(), UserId = zhangUser.Id, UserName = zhangUser.Name, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"Architecture"</span><span style="color:black;">, </span><span style="color:#a31515;">".NET"</span><span style="color:black;">, </span><span style="color:#a31515;">"Databases" </span><span style="color:black;">}, }; </span><span style="color:blue;">var </span><span style="color:black;">blogPosts = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPost</span><span style="color:black;">> { </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPost </span><span style="color:black;">{ Id = redisBlogPosts.GetNextSequence(), BlogId = yangBlog.Id, Title = </span><span style="color:#a31515;">"Memcache"</span><span style="color:black;">, Categories = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"DocumentDB" </span><span style="color:black;">}, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> {</span><span style="color:#a31515;">"Memcache"</span><span style="color:black;">, </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"JSON"</span><span style="color:black;">, </span><span style="color:#a31515;">".NET"</span><span style="color:black;">} , Comments = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPostComment</span><span style="color:black;">> { </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPostComment </span><span style="color:black;">{ Content = </span><span style="color:#a31515;">"First Comment!"</span><span style="color:black;">, CreatedDate = </span><span style="color:#2b91af;">DateTime</span><span style="color:black;">.UtcNow,}, </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPostComment </span><span style="color:black;">{ Content = </span><span style="color:#a31515;">"Second Comment!"</span><span style="color:black;">, CreatedDate = </span><span style="color:#2b91af;">DateTime</span><span style="color:black;">.UtcNow,}, } }, </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPost </span><span style="color:black;">{ Id = redisBlogPosts.GetNextSequence(), BlogId = zhangBlog.Id, Title = </span><span style="color:#a31515;">"Redis"</span><span style="color:black;">, Categories = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"Cache" </span><span style="color:black;">}, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> {</span><span style="color:#a31515;">"Redis"</span><span style="color:black;">, </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"Scalability"</span><span style="color:black;">, </span><span style="color:#a31515;">"Performance"</span><span style="color:black;">}, Comments = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPostComment</span><span style="color:black;">> { </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPostComment </span><span style="color:black;">{ Content = </span><span style="color:#a31515;">"First Comment!"</span><span style="color:black;">, CreatedDate = </span><span style="color:#2b91af;">DateTime</span><span style="color:black;">.UtcNow,} } }, </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPost </span><span style="color:black;">{ Id = redisBlogPosts.GetNextSequence(), BlogId = yangBlog.Id, Title = </span><span style="color:#a31515;">"Cassandra"</span><span style="color:black;">, Categories = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"Cluster" </span><span style="color:black;">}, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> {</span><span style="color:#a31515;">"Cassandra"</span><span style="color:black;">, </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"Scalability"</span><span style="color:black;">, </span><span style="color:#a31515;">"Hashing"</span><span style="color:black;">}, Comments = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPostComment</span><span style="color:black;">> { </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPostComment </span><span style="color:black;">{ Content = </span><span style="color:#a31515;">"First Comment!"</span><span style="color:black;">, CreatedDate = </span><span style="color:#2b91af;">DateTime</span><span style="color:black;">.UtcNow,} } }, </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPost </span><span style="color:black;">{ Id = redisBlogPosts.GetNextSequence(), BlogId = zhangBlog.Id, Title = </span><span style="color:#a31515;">"Couch Db"</span><span style="color:black;">, Categories = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> { </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"DocumentDB" </span><span style="color:black;">}, Tags = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:blue;">string</span><span style="color:black;">> {</span><span style="color:#a31515;">"CouchDb"</span><span style="color:black;">, </span><span style="color:#a31515;">"NoSQL"</span><span style="color:black;">, </span><span style="color:#a31515;">"JSON"</span><span style="color:black;">}, Comments = </span><span style="color:blue;">new </span><span style="color:#2b91af;">List</span><span style="color:black;"><</span><span style="color:#2b91af;">BlogPostComment</span><span style="color:black;">> { </span><span style="color:blue;">new </span><span style="color:#2b91af;">BlogPostComment </span><span style="color:black;">{Content = </span><span style="color:#a31515;">"First Comment!"</span><span style="color:black;">, CreatedDate = </span><span style="color:#2b91af;">DateTime</span><span style="color:black;">.UtcNow,} } }, }; yangUser.BlogIds.Add(yangBlog.Id); yangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == yangBlog.Id).Map(x => x.Id)); zhangUser.BlogIds.Add(zhangBlog.Id); zhangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == zhangBlog.Id).Map(x => x.Id)); redisUsers.Store(yangUser); redisUsers.Store(zhangUser); redisBlogs.StoreAll(</span><span style="color:blue;">new</span><span style="color:black;">[] { yangBlog, zhangBlog }); redisBlogPosts.StoreAll(blogPosts);
}</span></pre>
在方法中,首先在Redis中創建了三個強類型的IRedisTypedClient類型的對象redisUsers,redisBlogs,redisBlogPosts來保存用戶信息,博客信息,和文字信息。
var yangUser = new User { Id = redisUsers.GetNextSequence(), Name = "Eric Yang" };在新建用戶的時候,因為Id是自增字段,所以直接調用redisUsers這個client的GetNextSequence()方法就可以獲得一個自增的Id。
創建完用戶之后,接著創建博客信息:
var yangBlog = new Blog{ Id = redisBlogs.GetNextSequence(), UserId = yangUser.Id, UserName = yangUser.Name, Tags = new List<string> { "Architecture", ".NET", "Databases" }, };該博客有幾個標簽。
在接著創建該博客上發表的若干篇文章:
var blogPosts = new List<BlogPost> { new BlogPost { Id = redisBlogPosts.GetNextSequence(), BlogId = yangBlog.Id, Title = "Memcache", Categories = new List<string> { "NoSQL", "DocumentDB" }, Tags = new List<string> {"Memcache", "NoSQL", "JSON", ".NET"} , Comments = new List<BlogPostComment> { new BlogPostComment { Content = "First Comment!", CreatedDate = DateTime.UtcNow,}, new BlogPostComment { Content = "Second Comment!", CreatedDate = DateTime.UtcNow,}, } } }每一篇文章都有分類和標簽,以及評論。
然后需要給user的BlogsIds和blog的BlogPostIds賦值
yangUser.BlogIds.Add(yangBlog.Id); yangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == yangBlog.Id).Map(x => x.Id));
最后需要把這些信息保存到redis中。
//保存用戶信息 redisUsers.Store(yangUser); redisUsers.Store(zhangUser);//保存博客信息redisBlogs.StoreAll(new[] { yangBlog, zhangBlog });//保存所有的文章信息redisBlogPosts.StoreAll(blogPosts);現在,利用Redis Desktop Manager,可以查看Reidis中存儲的數據:
數據準備好了之后,可以實現前面列出的一系列方法了:
顯示所有博客
該方法在GetAllBlogs中,實現如下:
[Test]public void Show_a_list_of_blogs() { var redisBlogs = redis.As<Blog>(); var blogs = redisBlogs.GetAll(); blogs.PrintDump(); }只需要調用GetAll方法即可獲取內存中的所有指定類型的對象。
輸出結果為:
[ {
Id: 1, UserId: 1, UserName: Eric Yang, Tags: [ Architecture, .NET, Databases ], BlogPostIds: [ 1, 3 ] }, { Id: 2, UserId: 2, UserName: Fish Zhang, Tags: [ Architecture, .NET, Databases ], BlogPostIds: [ 2, 4 ] }
]</span></pre>
顯示最近發表的文章和評論
實現如下:
[Test]public void Show_a_list_of_recent_posts_and_comments() { //Get strongly-typed clients var redisBlogPosts = redis.As<BlogPost>(); var redisComments = redis.As<BlogPostComment>(); { //To keep this example let's pretend this is a new list of blog posts var newIncomingBlogPosts = redisBlogPosts.GetAll();</span><span style="color:green;">//Let's get back an IList<BlogPost> wrapper around a Redis server-side List. </span><span style="color:blue;">var </span><span style="color:black;">recentPosts = redisBlogPosts.Lists[</span><span style="color:#a31515;">"urn:BlogPost:RecentPosts"</span><span style="color:black;">]; </span><span style="color:blue;">var </span><span style="color:black;">recentComments = redisComments.Lists[</span><span style="color:#a31515;">"urn:BlogPostComment:RecentComments"</span><span style="color:black;">]; </span><span style="color:blue;">foreach </span><span style="color:black;">(</span><span style="color:blue;">var </span><span style="color:black;">newBlogPost </span><span style="color:blue;">in </span><span style="color:black;">newIncomingBlogPosts) { </span><span style="color:green;">//Prepend the new blog posts to the start of the 'RecentPosts' list </span><span style="color:black;">recentPosts.Prepend(newBlogPost); </span><span style="color:green;">//Prepend all the new blog post comments to the start of the 'RecentComments' list </span><span style="color:black;">newBlogPost.Comments.ForEach(recentComments.Prepend); } </span><span style="color:green;">//Make this a Rolling list by only keep the latest 3 posts and comments </span><span style="color:black;">recentPosts.Trim(0, 2); recentComments.Trim(0, 2); </span><span style="color:green;">//Print out the last 3 posts: </span><span style="color:black;">recentPosts.GetAll().PrintDump(); </span><span style="color:black;">recentComments.GetAll().PrintDump(); </span><span style="color:black;">}
}</span></pre>
方法中定義了兩個key為urn:BlogPost:RecentPosts 和 urn:BlogPostComment:RecentComments的 List對象來保存最近發表的文章和評論:recentPosts.Prepend(newBlogPost)方法表示將新創建的文章插到 recentPosts列表的最前面。
Trim方法表示僅保留n個在集合中。
顯示博客的標簽云
顯示博客的標簽云方法如下:
[Test]public void Show_a_TagCloud() { //Get strongly-typed clients var redisBlogPosts = redis.As<BlogPost>(); var newIncomingBlogPosts = redisBlogPosts.GetAll();</span><span style="color:blue;">foreach </span><span style="color:black;">(</span><span style="color:blue;">var </span><span style="color:black;">newBlogPost </span><span style="color:blue;">in </span><span style="color:black;">newIncomingBlogPosts) { </span><span style="color:green;">//For every tag in each new blog post, increment the number of times each Tag has occurred </span><span style="color:black;">newBlogPost.Tags.ForEach(x => redis.IncrementItemInSortedSet(</span><span style="color:#a31515;">"urn:TagCloud"</span><span style="color:black;">, x, 1)); } </span><span style="color:green;">//Show top 5 most popular tags with their scores </span><span style="color:blue;">var </span><span style="color:black;">tagCloud = redis.GetRangeWithScoresFromSortedSetDesc(</span><span style="color:#a31515;">"urn:TagCloud"</span><span style="color:black;">, 0, 4); tagCloud.PrintDump();
}</span></pre>
顯示標簽云的實現,用到了redis中的SortedSet,IncrementItemInSortedSet表示如果有相同的話,值加一,GetRangeWithScoresFromSortedSetDesc方法,獲取某一key的前5個對象。
顯示所有的分類
顯示所有的分類用到了Set對象。
[Test]public void Show_all_Categories() { var redisBlogPosts = redis.As<BlogPost>(); var blogPosts = redisBlogPosts.GetAll();</span><span style="color:blue;">foreach </span><span style="color:black;">(</span><span style="color:blue;">var </span><span style="color:black;">blogPost </span><span style="color:blue;">in </span><span style="color:black;">blogPosts) { blogPost.Categories.ForEach(x => redis.AddItemToSet(</span><span style="color:#a31515;">"urn:Categories"</span><span style="color:black;">, x)); } </span><span style="color:blue;">var </span><span style="color:black;">uniqueCategories = redis.GetAllItemsFromSet(</span><span style="color:#a31515;">"urn:Categories"</span><span style="color:black;">); uniqueCategories.PrintDump();
}</span></pre>
顯示文章以及其評論
實現如下:
[Test]public void Show_post_and_all_comments() { //There is nothing special required here as since comments are Key Value Objects //they are stored and retrieved with the post var postId = 1; var redisBlogPosts = redis.As<BlogPost>(); var selectedBlogPost = redisBlogPosts.GetById(postId.ToString());selectedBlogPost.PrintDump();
}</span></pre>
只需要把postId傳進去就可以通過GetById的方法獲取內存中的對象.
添加評論
首先根據PostId獲取BlogPost,然后在Comment屬性中添加一個BlogPostComment對象,然后在保存改BlogPost.
[Test]public void Add_comment_to_existing_post() { var postId = 1; var redisBlogPosts = redis.As<BlogPost>(); var blogPost = redisBlogPosts.GetById(postId.ToString()); blogPost.Comments.Add( new BlogPostComment { Content = "Third Post!", CreatedDate = DateTime.UtcNow }); redisBlogPosts.Store(blogPost);</span><span style="color:blue;">var </span><span style="color:black;">refreshBlogPost = redisBlogPosts.GetById(postId.ToString()); refreshBlogPost.PrintDump();
}</span></pre>
顯示分類以及分類對應的文章
[Test]public void Show_all_Posts_for_the_DocumentDB_Category() { var redisBlogPosts = redis.As<BlogPost>(); var newIncomingBlogPosts = redisBlogPosts.GetAll();</span><span style="color:blue;">foreach </span><span style="color:black;">(</span><span style="color:blue;">var </span><span style="color:black;">newBlogPost </span><span style="color:blue;">in </span><span style="color:black;">newIncomingBlogPosts) { </span><span style="color:green;">//For each post add it's Id into each of it's 'Cateogry > Posts' index </span><span style="color:black;">newBlogPost.Categories.ForEach(x => redis.AddItemToSet(</span><span style="color:#a31515;">"urn:Category:" </span><span style="color:black;">+ x, newBlogPost.Id.ToString())); } </span><span style="color:green;">//Retrieve all the post ids for the category you want to view </span><span style="color:blue;">var </span><span style="color:black;">documentDbPostIds = redis.GetAllItemsFromSet(</span><span style="color:#a31515;">"urn:Category:DocumentDB"</span><span style="color:black;">); </span><span style="color:green;">//Make a batch call to retrieve all the posts containing the matching ids //(i.e. the DocumentDB Category posts) </span><span style="color:blue;">var </span><span style="color:black;">documentDbPosts = redisBlogPosts.GetByIds(documentDbPostIds); documentDbPosts.PrintDump();
}</span></pre>
這里首先把所有的文章按照標簽新建Set,把相同的分類的文章放到一個Set中,最后根據key即可查找到相應的集合。
總結
本文利用一個簡單的博客系統,簡要介紹了如何利用Redis存儲和獲取復雜的數據。由于本文主要為了演示如何與Redis進行交互,所以實體設計的很簡陋,沒有按照DDD的思想進行設計,在某些設計方面沒有遵循前文淺談依賴注入中使用的原理和方法,后面會寫文章對該系統進行重構以使之更加完善。
希望本文對您了解如何利用Redis存儲復雜對象有所幫助。
參考資料