【问题标题】:How to AND predicates in the WHERE clause in a LINQ to RavenDB query如何在 LINQ to RavenDB 查询的 WHERE 子句中与谓词
【发布时间】:2012-12-07 00:45:25
【问题描述】:

我有以下型号:

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;
        }

我想获取所有在sinceNewState 之前具有(StateChange.CreatedAt"some state of interest")并且在now 和@987654330 之前没有(StateChange.CreatedAt 的记录的计数@ 是 "some state of interest")。

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

【问题讨论】:

  • “不起作用”是什么意思?有错误吗?
  • 不,这意味着它没有返回预期的结果,即忽略右侧表达式
  • 你怎么知道它忽略了它?如果第一个条件为真,它必须评估正确的条件才能得到整个条件结果。
  • @AmiramKorach 是的,这就是您在处理对象集合时所做的事情。但情况并非如此,谓词被转换为 Lucene 查询字符串。

标签: linq ravendb


【解决方案1】:

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

问题在于 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")));

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

【讨论】:

    猜你喜欢
    • 2011-09-03
    • 1970-01-01
    • 2011-06-24
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多