我将为每个用户提供一个活动源,显示与用户订阅的事件相关的所有活动,并且Feed将引入最近的20个左右的活动.我设置的方式是所有活动,无论与其相关的事件是否存储在一个集合中,文档本身都有一个我查询和索引的“事件”属性.基本查询只是从集合中选择活动,其中事件在按日期排序的用户事件订阅列表中.我存储了用户事件订阅列表的哈希值,并使用哈希作为xx秒的密钥来缓存查询结果,因此如果另一个用户订阅了相同的确切事件,我可以从缓存中提取结果,我是不关心结果是xx秒陈旧.
编辑:添加模型和查询示例
楷模:
User { // useless properties excluded // fixed: hashset not list,can be quite large HashSet<string> Subscriptions { get; set; } string SubscriptionHash { get; set; } // precomputed hash of all strings in subscriptions } Activity { // Useless properties excluded string ActivityType { get; set; } }
查询:
if (cache[user.SubscriptionHash] != null) results = (HashSet<Activity>)cache[user.SubscriptionHash]; else results = session.Query<Activity>().Where(user.Subscriptions.Contains(e => e.ActivityType)).Take(20).ToList(); // add results to cache
我担心的是,如果这是处理这个问题的最佳方法,或者是否有更好的ravendb伏都教可供使用.如果有很多活动,单个集合可能会增长到数百万,当有成千上万的用户拥有无限的订阅列表组合时,我可能会在缓存中存储数千个密钥.这些供稿位于用户登录页面上,所以它很多,我不想只是在这个问题上投入更多的硬件.
所以我真正想要的答案是,如果这是最好的查询,或者如果有更好的方法在Raven中使用list.Contains查询数百万个文档.
这是一个使用ravendb的asp.net 4.5 mvc 4项目.
解决方法
现在我将如何处理它.这是基于RaccoonBlog PostComments
我将每个用户事件存储在单独的文档中(即下面示例中的UserEvent),其中用户具有链接到它的附加属性以及与用户相关联的最后事件的多个事件和时间戳.这将使用户文档保持更小,但具有很多重要信息
在UserEvent中,它将是一个包含id的简单文档,指向此文档引用的用户标识的链接,“事件”集合和lasteventid.这样,如果需要,每个“事件”成为维护的子文档.
最后一个UserEvent索引,允许您轻松查询数据
public class User { public string Id { get; set; } // other user properties public string UserEventId { get; set; } public int NumberOfEvents { get; set; } public DateTimeOffset LastEvent { get; set; } } public class UserEvent { public string Id { get; set; } public string UserId { get; set; } public int LastEventId { get; set; } public ICollection<Event> Events { get; protected set; } public int GenerateEventId() { return ++LastEventId; } public class Event { public int Id { get; set; } public DateTimeOffset CreatedAt { get; set; } public string ActivityType { get; set; } // other event properties } } public class UserEvents_CreationDate : AbstractIndexCreationTask<UserEvent,UserEvents_CreationDate.ReduceResult> { public UserEvents_CreationDate() { Map = userEvents => from userEvent in userEvents from evt in userEvent.Events select new { evt.CreatedAt,EventId = evt.Id,UserEventId = userEvent.Id,userEvent.UserId,evt.ActivityType }; Store(x => x.CreatedAt,FieldStorage.Yes); Store(x => x.EventId,FieldStorage.Yes); Store(x => x.UserEventId,FieldStorage.Yes); Store(x => x.UserId,FieldStorage.Yes); Store(x => x.ActivityType,FieldStorage.Yes); } public class ReduceResult { public DateTimeOffset CreatedAt { get; set; } public int EventId { get; set; } public string UserEventId { get; set; } public string UserId { get; set; } public string ActivityType { get; set; } } } public static class Helpers { public static DateTimeOffset AsMinutes(this DateTimeOffset self) { return new DateTimeOffset(self.Year,self.Month,self.Day,self.Hour,self.Minute,self.Offset); } public static IList<Tuple<UserEvents_CreationDate.ReduceResult,User>> QueryForRecentEvents( this IDocumentSession documentSession,Func <IRavenQueryable<UserEvents_CreationDate.ReduceResult>,IQueryable<UserEvents_CreationDate.ReduceResult> > processQuery) { IRavenQueryable<UserEvents_CreationDate.ReduceResult> query = documentSession .Query<UserEvents_CreationDate.ReduceResult,UserEvents_CreationDate>() .Include(comment => comment.UserEventId) .Include(comment => comment.UserId) .OrderByDescending(x => x.CreatedAt) .Where(x => x.CreatedAt < DateTimeOffset.Now.AsMinutes()) .AsProjection<UserEvents_CreationDate.ReduceResult>(); List<UserEvents_CreationDate.ReduceResult> list = processQuery(query).ToList(); return (from identifier in list let user = documentSession.Load<User>(identifier.UserId) select Tuple.Create(identifier,user)) .ToList(); } }
然后你要做的就是查询.
documentSession.QueryForRecentEvents(q => q.Where(x => x.UserId == user.Id && x.ActivityType == "asfd").Take(20)).Select(x => x.Item1);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。