我有以下型号:
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
并且没有( now
前OldState
"some state of interest"
&& !.p.StateChanges.Any....
为{{1}}。
虽然上面使用的谓词在linq中起作用,但它似乎不能在linq中使用raven(即不返回预期的结果)。我怀疑这是因为如果左侧的表达式求值为true,则永远不会计算表达式{{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")));
当然,如果这是你想要的,你仍然可以统计它。