2012-04-12 68 views
4

子集至少所有元素查找對象我有簡單類型Question其中包含使用RavenDB和LINQ

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?

+0

不熟悉烏鴉驅動程序,但是嘗試不同的情況:例如包含,相交... – Tigran 2012-04-12 09:48:03

回答

6

亞雷克, 你想要做的是:

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

這會給你所有具有至少所有這些標籤的問題。

+0

的foreach迭代後,我已經查q變量的調試器,它被定義爲:{(標籤:BB)AND(標籤:BB)},這樣的東西是不正確的位置。我正在遍歷列表標記= [「aa」,「bb」]。第一個標籤已被埋在某處。 – jwaliszko 2012-04-12 16:03:50

+1

這可能與被捕獲的變量有關,因爲你有一個lambda。嘗試這裏的代碼https://gist.github.com/8016f3c8f9a6d8cd485f – 2012-04-12 16:55:59

+0

謝謝,在這裏顯示了類似的問題,並提供瞭解釋:http://confluence.jetbrains.net/display/ReSharper/Access+to+modified+closure – jwaliszko 2012-04-13 07:52:33

1

它看起來像LINQ提供程序沒有實現除了作爲查詢模式的一部分。如果我足夠了解您的需求,您可以使用SequenceEquals。

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

使用您提供的代碼,這隻返回一個結果{"aa","bb"}。如果RavenDB提供程序沒有爲您提供足夠的查詢模式實現,那麼就根本不使用LINQ即可。

+0

謝謝,但使用LINQ到該對象僅返回這個問題有相同的標籤,提供子集。所以這不是我想要達到的。此外,使用RavenDB時,此語法會引發另一個異常:「System.NotSupportedException:不支持的方法:SequenceEqual」。 – jwaliszko 2012-04-12 10:54:42

+0

然後拉出結果爲對象,不執行對RavenDB的查詢需要查詢模式轉換。 – 2012-04-12 18:13:36

0

RavenDB LINQ提供程序不支持此語法,因爲基礎索引機制(Lucene)不允許此類查詢。

但是,RavenDB中有一項新功能可以讓您執行此操作,有關更多信息,請參閱this thread注意您需要獲取最新版本才能使用此功能。

你應該能夠編寫查詢爲:

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 } 

謝謝,我一直在尋找另一個場景此新功能,所以當我有機會時,我會創建一個顯示完整樣本的要點。

+0

我已經建造#888(服務器和客戶端),但我得到一個異常,而使用你的小費嘗試:System.NotSupportedException:方法不支持:相交。有沒有其他方法可以做到這一點? – jwaliszko 2012-04-12 16:55:46