如何在LINQ to RavenDB查询的WHERE子句中进行AND谓词 [英] How to AND predicates in the WHERE clause in a LINQ to RavenDB query

查看:98
本文介绍了如何在LINQ to RavenDB查询的WHERE子句中进行AND谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下模型:

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

我想获取所有具有since并且NewState"some state of interest"之前的StateChange.CreatedAt并且nowStateChange.CreatedAt的所有Clip记录的计数>是"some state of interest").

I want to get the count for all Clip records that have a (StateChange.CreatedAt before since and NewState is "some state of interest") AND NOT have a (StateChange.CreatedAt before now and OldState is "some state of interest").

虽然以上使用的谓词在linq中可以对对象起作用,但它似乎在linq中却无法起作用(即不返回预期结果).我怀疑这是因为如果左侧的表达式的值为true,则永远不会对表达式&& !.p.StateChanges.Any....进行求值.有办法解决这个问题吗?

While the predicate used above works in linq to object, it doesn't seem to work in linq to raven (i.e. does not return the expected result). I suspect that this is because the expression && !.p.StateChanges.Any.... is never evaluated if the expression on the left-hand side evaluates to true. Is there a way to work around this?

推荐答案

与条件评估无关. &&效果很好.

It's not related to the evaluation of conditions. && works just fine.

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

The problem is that RavenDB doesn't properly handle queries that use .All(...) or !.Any(...). This is due to the way raven's dynamic index engine evaluates your linq statement. It wants to build a separate index entry for each of your StateChange entries, which won't work for operations that need to consider multiple related items, such as the different state changes.

此处中已经记录了一个问题.在尝试以这种方式查询时,它在内部版本2151中已关闭,以抛出有意义的异常.也许将来某个时候,他们可以重新评估是否有某种方法可以真正正确地评估这些类型的查询.

There is an issue already logged for this here. It was closed in build 2151 to throw back a meaningful exception when you try to query in this way. Maybe at some future date they can reassess if there's some way to actually evaluate these types of queries properly instead.

更新

我一直在考虑您的挑战,并且另一个相关的人,并且能够提出一个新的建议.技术,使您可以执行此操作.它将需要一个静态索引和Lucene查询:

I've been thinking about your challenge, and another related one, and was able to come up with a new technique that will allow you to do this. It will require a static index and lucene query:

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")));

当然,如果您想要的话,您仍然可以对其进行统计.

Of course, you can still just take statistics on it if that's what you want.

这篇关于如何在LINQ to RavenDB查询的WHERE子句中进行AND谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆