.NET中使用Redis (二)

jopen 10年前發布 | 39K 次閱讀 Redis NoSQL數據庫

很久以前寫了一篇文章 .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了。

    .NET中使用Redis (二)

    在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; }
    }

     .NET中使用Redis (二)

    具體實現

    實體定義好了之后,我們就可以開始具體實現了。為了演示,這里通過單元測試的方式實現具體功能:

    首先要把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中存儲的數據:

    .NET中使用Redis (二)

    數據準備好了之后,可以實現前面列出的一系列方法了:

    顯示所有博客

    該方法在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存儲復雜對象有所幫助。

     

    參考資料

    1. Designing NoSql Database
    2. Migrations Using Schemaless NoSql
    3. That No SQL Thing: The relational modeling anti pattern in document databases
    4. </ol> </div> 作者: yangecnuyangecnu's Blog on 博客園
      出處: http://www.cnblogs.com/yangecnu/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!