【问题标题】:RavenDB static index on document with dynamic field具有动态字段的文档上的 RavenDB 静态索引
【发布时间】:2012-10-15 19:42:29
【问题描述】:

我正在尝试为以下示例类创建静态索引:

public class Board {
...other assorted fields
List<dynamic> Messages {get; set;}
internal Board() {Messages = new List<dynamic>();}
}

该索引用于过滤具有早于某个日期的消息的板。目的是对今天到期的消息执行“更新”操作,更新它们的内容,并将它们持久化。需要该索引以避免遍历所有客户端的所有消息,因为这可能在计算上很昂贵。 Messages 是从包含 ExpiryDate 属性的基类继承的消息类型列表。

尝试创建如下索引会导致“表达式树可能不包含 动态操作”错误。我知道动态类型不能很好地与 Linq 查询一起使用,因此需要在 RavenDB 中使用 LuceneQueries 而不是 Query()。有没有办法让这个索引与动态属性一起工作?谢谢!

 public class ScanBoardMessagesIndex : AbstractIndexCreationTask<Board>
  {
    public ScanBoardMessagesIndex () {
      Map = boards => from board in boards
                     where board.Messages.Any(msg => ((MessageItem) msg).ExpiryDate <= DateTime.UtcNow.Date)
                     select board;
    }
  }

编辑:

我遇到了 raven 序列化问题,因为现有 Board 文档的元数据 clr 类型被设置为不再有效的类命名空间。我正在做一个迁移项目,所以我继续并首先发布了一个补丁来更改现有文档的元数据 clr 类型,然后再将它们迁移到使用基/抽象类作为消息列表而不是类型动态的新数据结构。

【问题讨论】:

    标签: dynamic indexing ravendb


    【解决方案1】:

    Map/Reduce 索引似乎更适合给定的要求。实际上,您希望能够按板中消息的最早到期日期查询板。这是一个聚合操作,正是 Map/Reduce 旨在解决的问题。此外,使用消息的基类将允许您定义索引,而无需求助于较低级别的IndexDefinition

    public class Message
    {
        public DateTime ExpiryDate { get; set; }
    }
    
    public class Board
    {
        public string Id { get; set; }
        public List<Message> Messages { get; set; }
    }
    
    public class OldestExpiryDateMessageInBoard : AbstractIndexCreationTask<Board, OldestExpiryDateMessageInBoard.Result>
    {
        class Result
        {
            public string BoardId { get; set; }
            public DateTime OldestExpiryDate { get; set; }
        }
    
        public OldestExpiryDateMessageInBoard()
        {
            this.Map = boards => from board in boards
                                 from message in board.Messages
                                 select new
                                 {
                                     BoardId = board.Id,
                                     OldestExpiryDate = message.ExpiryDate
                                 };
    
            this.Reduce = results => from result in results
                                     group result by result.BoardId into g
                                     select new
                                     {
                                         BoardId = g.Key,
                                         OldestExpiryDate = g.Min(x => x.OldestExpiryDate)
                                     };
        }
    }
    

    然后您可以使用 Lucene 语法查询此索引。

    【讨论】:

    • 感谢 eulerfx。基类 Messages 是一个抽象类,当类 Board 被持久化时,它会导致 RavenDB 中的序列化问题,因此属性 Messages 被定义为动态对象的列表。
    • 你遇到了什么样的序列化问题?
    • eulerfx,序列化问题是因为元数据 clr-type 设置为不再有效的类命名空间。我正在做一个迁移项目,所以我继续并首先发布了一个补丁来更改现有文档的元数据 clr 类型,然后再将它们迁移到新的数据结构。我接受了你的回答,因为它为一个密切相关的问题提供了解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    相关资源
    最近更新 更多