3

我正在和 Raven 一起玩,并试图找出为类似 twitter 的场景建模我的对象的最佳方法。到目前为止,我已经提出了一些选择,但不确定哪个是最好的。

public class User{
    public string Id{get;set;}
    public List<string> Following{get;set;}
    public List<string> Followers{get;set;}
}

User 对象简单明了,只是一个 ID 和我关注的人和关注我的人的 ID 列表。提要设置是我需要帮助的地方,可以从我关注的用户那里获取所有帖子。

选项 1 - 简单的路线

这仅根据他们的 UserId 搜索我关注的人的所有帖子。

public class Post{
    public string UserId{get;set;}
    public string Content{get;set;}
}

指数

public class Posts : AbstractIndexCreationTask<Post>{
    public Posts(){
        Map = results => from r in results
                         select new{
                             r.UserId
                         };
    }
}

查询

var posts = session.Query<Post,Posts>().Where(c=>c.UserId.In(peopleImFollowing));

这是显而易见的路线,但闻起来很臭。该查询导致发送到 Lucene 的一堆 OR 语句。Raven 可以处理的上限约为 1024,因此任何一个用户都不能关注超过 1000 人。

选项 2 - 每个关注者一个帖子

public class Post{
    public string UserId{get;set;}
    public string RecipientId{get;set;}
    public string Content{get;set;}
}

添加新帖子

foreach(string followerId in me.Followers){
   session.Store(new Post{
    UserId = me.UserId,
    RecipientId = followerId,
    Content = "foobar" });
}

这很容易理解,也很容易查询,但似乎创建的文档太多了……也许这并不重要?

选项 3 - 收件人列表

到目前为止,我最喜欢这个。

public class Post{
    public string UserId{get;set;}
    public List<string> Recipients{get;set;}
    public string Content{get;set;}
}

指数

public class Posts : AbstractIndexCreationTask<Post>{
    public Posts(){
        Map = results => from r in results
                         select new{
                             UserId = r.UserId,
                             Recipient = r.Recipients
                         }
    }
}

添加新帖子

session.Store(new Post{
               UserId = me.Id,
               Recipients = me.Followers,
               Content = "foobar"
              });

查询

var posts = session.Query<Post,Posts>().Where(c=>c.Recipient == me.Id);

这似乎是最好的方法,但我以前从未使用过 Lucene。如果有人有 10,000 个关注者,那么索引会不会有问题?如果我们想向每个用户发布一条消息怎么办?也许还有另一种方法?

4

1 回答 1

1

从我的角度来看,只有选项 1 真正有效,如果您希望支持超过 1024 个用户,您可能需要调整 RavenDB 与 lucene 的对话方式。

选项 2 和选项 3没有考虑到,在您关注新用户后,您希望他们的旧推文出现在您的时间线中。同样,您还希望这些推文在您取消关注后从您的时间线上消失。如果您想使用这两种方法之一来实现这一点,您需要在“关注”操作中复制他们的所有推文,并在“取消关注”时删除它们。这将使关注/取消关注成为一项非常昂贵的操作,并且它也可能失败(如果在您执行此操作时包含部分推文的服务器不可用怎么办?)。

选项 2也有一个巨大的缺点,即它会产生大量的重复数据。想想拥有数百万追随者和数千条帖子的著名用户。然后将其与成千上万的著名用户相乘……甚至 twitter 也无法处理如此大量的数据。

选项 3还存在查询索引变慢的问题,因为每个 lucene 文档都会有这个“收件人”字段,可能有数百万个值。而且您拥有数万亿个文档...不,我不是 lucene 专家,但我认为它的工作速度不足以显示时间线(即使您不是唯一想要显示时间线的并发用户)。

正如我上面所说,我认为只有选项 1 有效。也许其他人有更好的方法。顺便说一句,好问题。

于 2012-05-13T23:32:05.420 回答