2

我正在使用 LinqPad 通过查询 NetFlix OData 源来学习 Linq。

(顺便说一句,我知道他们已经在 SO 上提出了类似的问题……对我没有帮助)。

这是我正在工作的查询,非常棒。

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 个结果。

第二(也是最重要的)。我想按流派的部分字符串进行过滤。每个标题都包含一个流派集合。我只想显示名称包含某个字符串(如“家庭”)的流派。使用包含“firstFilter”和“secondFilter”的标题更好地过滤。

基本上,我想按流派过滤,但我不知道该怎么做,因为 Title 包含它自己的 Genres 集合,我不知道如何只返回集合中一种或多种流派的标题。

谢谢你的帮助!

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

赛斯

4

3 回答 3

4

要返回前 10 个结果,请将上面的代码用括号括起来,并在最后放置一个 .Take(10)

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

目前没有办法在 C# 中使用查询语法。

至于流派过滤器,正如 klabranche 指出的那样,oData 不支持您可以在本地使用常规 IEnumerable 或 IQueryable 的许多相同 Linq 构造。

klabranche 的解决方案不支持包含。但是,它确实需要对服务器进行 2 次往返以获得结果。(请参阅我对他的回答的评论,了解为什么这似乎是必要的)

这是一种替代方法,它往返于服务器以获取数据,然后在本地处理该数据。因为某些查询在本地运行,您可以使用 string.Contains、“或”子句和其他优点。

这种方法的缺点是它通过网络检索的数据多于回答查询所需的数据。另一方面,它很容易理解并且有效。

当我结合“家庭”和“儿童”时,它返回 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();
于 2010-09-18T17:41:39.127 回答
1

要获得前 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 不支持Select Many 查询,这就是为什么 contains 失败或尝试 OR 流派名称的原因。

以下失败,因为包含返回许多...

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# 语句而不是表达式):

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;
于 2010-09-18T19:56:52.687 回答
1

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)
于 2010-09-18T17:42:22.020 回答