【问题标题】:Select products that has all tags选择具有所有标签的产品
【发布时间】:2014-04-02 13:10:19
【问题描述】:

我正在使用 C# 和实体框架。我有一个包含我的产品的 Products 表 (Id, Name)、一个包含所有可用标签的 Tags 表 (Id, Name) 和一个用于为产品分配标签的 ProductTags 表 (Id, ProductId, TagId)。 用户可以指定他想查看具有多个标签的产品 (Int[] SelectedTagIds)。 问题是:如何获取所有产品,每个产品都有用户指定的所有标签。

现在我正在使用这个查询

`var reault = Context.Products
                     .Where(x => SelectedTagIds.All(y => 
                           (x.ProductTags.Select(z => z.TagId))
                     .Contains(y)));`

我想知道这是正确的方法还是有更好/更快的方法?

【问题讨论】:

  • 您是否遇到实际性能问题或尝试提前优化?
  • @Oren 我正在尝试优化建议,因为项目现在正在开发中,数据库中只有 10 个测试产品/3 个测试标签...
  • 优化的最佳方式是避免理论化,并实际保留大量标签和产品及其关联——最好比您未来预期的数量略大。然后,您可以测试性能是否可以接受,而不是猜测不同的方法是否会更好。

标签: c# linq entity-framework


【解决方案1】:

您可以使用 intersect 然后检查两者的长度,确保 intersect 与搜索标签的计数相同,这意味着所有搜索标签都存在于 ProductTags 集合中。

        var result =
            products.Where(
                x => x.ProductTags.Intersect(searchTags).Count() == searchTags.Length);

但您需要运行对您更有效的性能分析。但正如 Oren 评论的那样,你真的有性能问题吗?由于这两个集合很可能都很小,因此不会造成瓶颈。

编辑:刚刚检查了 intersect 的性能,它比使用 .All 和 .Contains 慢

Perf 在我的机器上创建 1000 个结果查询并使用 ToList() 在一组 1000 个产品上枚举它们,带有 2 个搜索标签,这给了我以下性能:

searchTags.All(search => x.ProductTags.Contains(search)) = 202ms

!searchTags.Except(x.ProductTags).Any() = 339ms

x.ProductTags.Intersect(searchTags).Count() == searchTags.Length = 389ms

如果你真的需要提高性能,你可以为你的 ProductTags 和 SelectedTagIds 使用 HashSet

编辑 2:使用 HashSet 比较

使用哈希集运行比较并获得以下输出,创建 1000 个查询对象并使用 ToList() 执行到列表中得到以下结果:

使用List<Tag>

Creating Events took 6ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 5379ms - Found 51
.Intersect = 5823ms - Found 51
.Except = 6720ms - Found 51

使用HashSet<Tag>

Creating Events took 26ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 259ms - Found 51
.Intersect = 6417ms - Found 51
.Except = 7347ms - Found 51

如您所见,使用 HashSet 的速度要快得多,即使您考虑到额外的 20 毫秒来创建 HashSet。虽然散列是 ID 字段的简单散列。如果你要使用更复杂的 Hash 结果会有所不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-14
    • 2015-03-31
    • 2011-04-04
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 2013-11-22
    相关资源
    最近更新 更多