4

私は単純なタイプを持っていますQuestion:

public class Question
{
    public Question(string id)
    {
        Id = id;
        Tags = new List<string>();
    }

    public string Id { get; private set; }
    public IList<string> Tags { get; set; }            
}

そのような質問のサンプル コレクションを定義しました。

var q1 = new Question("q1") { Tags = new List<string>() {"aa", "bb"} };
var q2 = new Question("q2") { Tags = new List<string>() {"aa"} };
var q3 = new Question("q3") { Tags = new List<string>() {"aa", "bb", "cc"} };
var q4 = new Question("q4");
var questions = new List<Question>() {q1, q2, q3, q4};

次に、指定されたサブセットから、少なくともすべてのタグを含むすべての質問を見つける必要があります。サブセットは以下で定義されます。

string[] tags = new[] {"aa", "bb"};

目的の結果を得るために使用するクエリは次のとおりです。

var result = questions.Where(x => !tags.Except(x.Tags).Any()).ToList();

結果は 2 つの質問のリストです: q1q3は、linq-to-objects を使用している間は適切に機能します。

残念ながら、現在 RavenDB に保持されているこのような質問をクエリしようとすると、例外が発生します。

var result = DocumentSession.Query<Question>()
                     .Where(x => !tags.Except(x.Tags).Any()).ToList();

結果:

System.InvalidOperationException: Cannot understand how to translate value(Core.Commands.GetQuestions+<>c__DisplayClass0).tags.Except(x.Tags)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetPath(Expression expression, String& path, Type& memberType, Boolean& isNestedPath)
   at Raven.Client.Linq.DynamicQueryProviderProcessor`1.GetMember(Expression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitAny(MethodCallExpression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitEnumerableMethodCall(MethodCallExpression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitQueryableMethodCall(MethodCallExpression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetLuceneQueryFor(Expression expression)
   at Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression)
   at Raven.Client.Linq.DynamicRavenQueryProvider`1.Execute(Expression expression)
   at Raven.Client.Linq.DynamicRavenQueryProvider`1.System.Linq.IQueryProvider.Execute(Expression expression)
   at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
...

RavenDB を使用して必要なことを実行するにはどうすればよいですか?

4

3 に答える 3

6

ジャレク、あなたがしたいことは:

var q = session.Query<Question>();
foreach(var tag in tags)
{
    var currentTag = tag;
    q = q.Where(x=>x.Tags.Any(xTag=>xTag == currentTag));
}

これにより、少なくともこれらすべてのタグを持つすべての質問が表示されます。

于 2012-04-12T11:09:30.940 に答える
1

LINQ プロバイダーは、Except をクエリ パターンの一部として実装していないようです。あなたの要件を十分に理解していれば、SequenceEquals を使用できるかもしれません。

var result = questions.Where(q => q.Tags.SequenceEqual(tags));

あなたが提供したコードを使用すると、これは正確に 1 つの結果を返し{"aa","bb"}ました。RavenDB プロバイダーが十分なクエリ パターンの実装を提供しない場合は、LINQ をまったく使用せずに実行してください。

于 2012-04-12T09:58:00.583 に答える
0

RavenDB LINQ プロバイダーは、基になるインデックス メカニズム (Lucene) がこのタイプのクエリを許可していないため、この構文をサポートしていません。

ただし、これを可能にする RavenDB の新機能があります。詳細については、このスレッドを参照してください。この機能を使用するには、最新のビルドを入手する必要があることに注意してください。

クエリは次のように記述できるはずです。

var result = session.Query<Question>("IndexName")
        .Where(x => x.Tags.Any(t => t == "aa"))
        .Intersect()
        .Where(x => x.Tags.Any(t => t == "bb")
        .ToList();

そして、インデックスは次のようにする必要があります。

from qu in docs.Questions
from tag in qu.Tags
select new { tag }

ありがとう、この新機能の別のシナリオを探していたので、機会があれば完全なサンプルを示す要点を作成します。

于 2012-04-12T10:28:02.880 に答える