簡體   English   中英

我如何使用linq對集合對象執行WHERE操作(使用Netflix數據源)

[英]How do I use linq to do a WHERE against a collection object (using Netflix data source)

我正在使用LinqPad通過查詢NetFlix OData源來學習Linq。

(順便說一句,我知道他們已經是一個類似的問題,所以……對我沒有幫助)。

這是我得到的查詢,很棒。

from x in Titles
//where x.Rating=="PG"
where x.Instant.Available==true
where x.AverageRating>=4.0
//where x.Rating.StartsWith("TV")
//where x.Genres.First (g => g.Name.Contains("Family") ) //(from y in Genres where y.Name.Contains("Family") select y)
//where x.Genres.First (g => g.Name=="")
//orderby x.Name
orderby x.AverageRating descending
//select x
//)
select new {x.Name, x.Rating, x.AverageRating, x.ShortSynopsis}

(請原諒所有評論……這證明了我正在嘗試的事實,並且我將針對各種需求更改查詢)。

有兩件事我無法弄清楚。

第一。 假設我只想返回前10個結果。

第二(也是最重要的)。 我想按該類型的部分字符串進行過濾。 每個標題都包含一個流派集合。 我只想顯示名稱包含某個字符串(例如“家庭”)的流派。 使用genre.name。包含“ firstFilter”和“ secondFilter”的標題的更好的過濾器。

基本上,我想按流派進行過濾,因為Title包含其自己的流派集合,所以我無法弄清楚該如何做,而且我也無法弄清楚如何僅返回該集的一種或多種流派的標題。

謝謝你的幫助!

ps ...似乎Netflix OData源不支持Any運算符。

賽斯

要返回前10個結果,請在上方用括號括起來,並在末尾添加.Take(10)

var foo = ( from x in Titles... ).Take(10);

目前尚無辦法在C#中使用查詢語法。

至於類型過濾器,正如klabranche指出的那樣,oData不支持許多可以在本地使用常規IEnumerable或IQueryable的相同Linq構造。

klabranche的解決方案不支持包含。 但是,它確實往返服務器兩次以獲得結果。 (請參閱我對他的回答的評論,以了解為什么這似乎是必要的)

這是一種替代方法,它使服務器往返一次以獲取數據,然后在本地處理該數據。 由於某些查詢在本地運行,因此可以使用string.Contains,“ or”子句和其他優點。

這種方法的缺點是,它通過網絡檢索比回答查詢所需的數據更多的數據。 另一方面,它很容易理解並且有效。

當我組合“家庭”和“孩子”時,它返回21個結果。

var oDataQuery = from x in Titles
                 where x.AverageRating >= 4
                    && x.Instant.Available==true       
                 orderby x.AverageRating descending
                 select new {x.Name, x.Rating, x.AverageRating, x.ShortSynopsis, x.Genres};

var localQuery = from o in oDataQuery.ToList()
                 where o.Genres.Any(g => g.Name.Contains("Family"))
                    && o.Genres.Any(g => g.Name.Contains("Children"))
                 select new {o.Name, o.Rating, o.AverageRating, o.ShortSynopsis };

localQuery.Dump();

OData和Netflix API支持Take()和Contains()方法:

from t in Titles
where t.Name.Contains("Matrix")
select t

(from t in Titles
where t.Name.Contains("Matrix")
select t).Take(10)

要獲得前10個:

(from x in Titles
where x.Instant.Available==true 
where x.AverageRating>=4.0 
orderby x.AverageRating descending 
select new {x.Name, x.Rating, x.AverageRating, x.ShortSynopsis}
).Take(10)

要按單一類型過濾(不是您想要的...):

from g in Genres
from t in g.Titles 
where g.Name == "Horror" 
where t.Instant.Available==true
where t.AverageRating >=4.0
orderby t.AverageRating descending 
select new {t.Name, t.Rating, t.AverageRating, t.ShortSynopsis}

但是, 您希望具有多種類型,但OData不支持“ 選擇許多”查詢 ,這就是為什么包含失敗或試圖對類型名稱進行“或”操作的原因。

以下失敗,因為包含返回許多...

var q1 = from g in Genres
from t in g.Titles 
where g.Name.Contains("Horror")
where t.Instant.Available==true
where t.AverageRating >=4.0
orderby t.AverageRating descending 
select new {t.Name, t.Rating, t.AverageRating, t.ShortSynopsis};

我發現要按多種類型過濾,您可以使用Concat或Union查詢 (在LinqPad中,請確保更改為C#語句而不是expression):

var q1 = from g in Genres
from t in g.Titles 
where g.Name=="Horror"
where t.Instant.Available==true
where t.AverageRating >=4.0
orderby t.AverageRating descending 
select new {t.Name, t.Rating, t.AverageRating, t.ShortSynopsis};

var q2 = from g in Genres
from t in g.Titles 
where g.Name=="HBO"
where t.Instant.Available==true
where t.AverageRating >=4.0
orderby t.AverageRating descending 
select new {t.Name, t.Rating, t.AverageRating, t.ShortSynopsis};

var concat = q1.ToList().Concat(q2);
//var union = q1.Union(q2);

通過合並這兩個查詢,它將刪除重復項,但是這些正是您想要的。如果我正確地理解了您想要的電影僅屬於這兩種類型,那么您會想要這些嗎?

在這種情況下,您將需要使用Concat來返回所有記錄。

現在,您只需要查找查詢中不止一次的記錄,就可以得到結果:

var results = from c in concat
group c by c.Name into grp
where grp.Count() > 1
select grp;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM