如何在LINQ to RavenDB查询的WHERE子句中使用AND谓词

时间:2012-12-05 12:43:46

标签: linq ravendb

我有以下型号:

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 since之前NewState"some state of interest"StateChange.CreatedAt并且没有( nowOldState "some state of interest" && !.p.StateChanges.Any....为{{1}}。

虽然上面使用的谓词在linq中起作用,但它似乎不能在linq中使用raven(即不返回预期的结果)。我怀疑这是因为如果左侧的表达式求值为true,则永远不会计算表达式{{1}}。有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:3)

这与条件评估无关。 &安培;&安培;工作得很好。

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

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

<强>更新

我一直在考虑你的挑战,another related one,并且能够提出一种新技术,让你可以做到这一点。它需要一个静态索引和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")));

当然,如果这是你想要的,你仍然可以统计它。