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

( beforeとis ) を持ち、かつ ( beforeとis )Clipを持たないすべてのレコードのカウントを取得したいと考えています。StateChange.CreatedAtsinceNewState"some state of interest"StateChange.CreatedAtnowOldState"some state of interest"

上で使用した述語は linq to object では機能しますが、linq to raven では機能しないようです (つまり、期待される結果が返されません)。&& !.p.StateChanges.Any....これは、左辺の式が true と評価された場合、その式が評価されないためだと思われます。これを回避する方法はありますか?

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 に答える