繁体   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