[英]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.