1

我有以下模型:

public class Clip {
    public Guid ClipId { get; set; }
    public IList<StateChange> StateChanges { get; set; }
}

public class StateChange {
    public string OldState { get; set; }
    public string NewState { get; set; }
    public DateTime ChangedAt { get; set; }
}

这就是查询乌鸦的方式:

var now = DateTime.UtcNow;
var since = now.AddSeconds(60);
string state = "some state of interest";
using (var session = docStore.OpenSession()) {
            RavenQueryStatistics stats;
            session.Query<Clip>()
                .Statistics(out stats)
                .Where(
                    p => p.StateChanges.Any(a => (since > a.ChangedAt && a.NewState == state))
                    && !p.StateChanges.Any(a => (a.OldState == state && now > a.ChangedAt)))
                .ToArray();
            return stats.TotalResults;
        }

我想获取所有Clip具有(StateChange.CreatedAt之前sinceNewState"some state of interest")且没有(StateChange.CreatedAt之前nowOldState是)的记录的计数"some state of interest"

虽然上面使用的谓词适用于 linq to object,但它似乎不适用于 linq to raven(即不返回预期结果)。我怀疑这是因为&& !.p.StateChanges.Any....如果左侧的表达式评估为真,则永远不会评估该表达式。有没有办法解决这个问题?

4

1 回答 1

3

它与条件的评估无关。&& 工作得很好。

问题是 RavenDB 不能正确处理使用 .All(...) 或 !.Any(...) 的查询。这是由于 raven 的动态索引引擎评估您的 linq 语句的方式。它希望为您的每个 StateChange 条目构建一个单独的索引条目,这对于需要考虑多个相关项目的操作(例如不同的状态更改)不起作用。

这里已经记录了一个问题。当您尝试以这种方式查询时,它已在构建 2151 中关闭以抛出有意义的异常。也许在将来的某个日期,他们可以重新评估是否有某种方法可以正确地评估这些类型的查询。

更新

我一直在考虑你的挑战,以及另一个相关的挑战,并且能够想出一种新技术来让你做到这一点。它将需要一个静态索引和 lucene 查询:

public class Clips_ByStateChange : AbstractIndexCreationTask<Clip>
{
  public Clips_ByStateChange()
  {
    Map = clips =>
          from clip in clips
          select new {
              OldState = clip.StateChanges
                  .Select(x => x.OldState + "|" + x.ChangedAt.ToString("o")),
              NewState = clip.StateChanges
                  .Select(x => x.NewState + "|" + x.ChangedAt.ToString("o"))
          };
  }
}

var results = session.Advanced.LuceneQuery<Clip, Clips_ByStateChange>()
    .Where(string.Format(
        "NewState: {{{0}|* TO {0}|{1}}} AND -OldState: {{{0}|* TO {0}|{2}}}",
        state, since.ToString("o"), now.ToString("o")));

当然,如果您愿意,您仍然可以对其进行统计。

于 2012-12-05T15:45:03.370 回答