【问题标题】:Improving a MongoDB LINQ expression to avoid for each loop改进 MongoDB LINQ 表达式以避免每个循环
【发布时间】:2014-08-11 11:49:21
【问题描述】:

我正在通过 C# 驱动程序查询 mongodb 集合,但无法提出可以根据每个类别的子类别限制删除项目的 LINQ 表达式。在下面的测试中,如果 Item 属于 Category 22 并且 Item 也属于 SubCategory A 或 B,则不应从查询中返回 Item。

当前编写的测试通过了,但我觉得有更好的方法可以在不使用 foreach 循环的情况下做到这一点。有什么想法吗?

[Test]
public void RemoveItemsBasedOnCategorySubCategoryRestrictions()
{
    var restrictionsByCategorySubCategories = new Dictionary<String, List<String>> {
        { "22", new List<String> { "A", "B" } },
        { "32", new List<String> { "A" } }
    };

    var items = new List<Item> { 
        new Item { Category = "32", SubCategory = new List<String> { "Z" } },
        new Item { Category = "32", SubCategory = new List<String> { "A" } }, 
        new Item { Category = "22", SubCategory = new List<String> { "Z" } },
        new Item { Category = "22", SubCategory = new List<String> { "A" } },
        new Item { Category = "22", SubCategory = new List<String> { "B" } } 
    }.AsQueryable();

    var results = new List<Item>();

    foreach (var restrictionsByCategorySubCategory in restrictionsByCategorySubCategories)
    {
        var category = restrictionsByCategorySubCategory.Key;
        var subCategories = restrictionsByCategorySubCategory.Value;

        results.AddRange(items.Where(p => p.Category.Equals(category) && !p.SubCategory.ContainsAny(subCategories)));
    }

    Assert.That(results.ToList(), Has.Count.EqualTo(2));

    foreach (var result in results)
    {
        Assert.That(result.SubCategory, Is.Not.EqualTo("A"));
        Assert.That(result.SubCategory, Is.Not.EqualTo("B"));
    }
}

项目:

class Item
{
    public String Category;
    public List<String> SubCategory;
}

【问题讨论】:

    标签: c# linq mongodb mongodb-.net-driver


    【解决方案1】:

    我将使用restrictions 字典名称而不是restrictionsByCategorySubCategories 来使代码更紧凑:

    var results =  items.Where(i =>
         !restrictions.ContainsKey(i.Category) ||
         !restrictions[i.Category].Intersect(i.SubCategory).Any());
    

    或者查询语法:

    var results = 
       from i in items
       where !restrictions.ContainsKey(i.Category) ||              
             !restrictions[i.Category].Intersect(i.SubCategory).Any()
       select i;
    

    逻辑非常直截了当 - 您会得到在受限列表中没有其类别的项目,或者在受限类别子类别中没有任何子类别的项目。

    结果:

    [
      { Category: "32", SubCategory: [ "Z" ] },
      { Category: "22", SubCategory: [ "Z" ] }
    ]
    

    不知道 Linq to MongoDb 是否可以翻译此查询,但您的代码没有任何 Linq to MongoDb - 它只是 Linq to Objects。

    【讨论】:

    • 谢谢...但正如您所怀疑的,MongoDB 驱动程序无法翻译它。
    • @jsmorris 然后我怀疑使用单个 Linq 到 MongoDb 查询的可能性。顺便说一句,正如我已经提到的,您有 Linq to Objects 查询。 MongoDb 在哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    相关资源
    最近更新 更多