【问题标题】:Get Collection (Products) of Objects for each item in a list获取列表中每个项目的对象集合(产品)
【发布时间】:2020-02-06 15:36:54
【问题描述】:

我有包含products 集合的orders 集合。我将一些产品ID 作为列表传递给方法。我需要返回与input 列表中的任何ID 匹配的产品列表。

我需要像这样使用 foreach 循环吗?请指教..

   public List < ProductOrderData > ListProductsByOrderId(List < Guid > input) {
      List < ProductOrderData > products = new List < ProductOrderData > ();
      foreach(var id in input) {
        var orders = this.Collection.AsQueryable().SelectMany(order => order.Products.Where(product => product.Id == id));
      }

    }

更新:

更新2:

更新 3: 我传递了产品 ID,我需要从与产品 ID 匹配的订单中获取产品列表。

【问题讨论】:

  • 请问是Collection 吗?一些物化集合,如List&lt;T&gt;,数组T[]?
  • @DmitryBychenko 请查看更新...
  • 为什么要截图?你不能只是复制粘贴为文本吗?
  • “我需要像这样使用 foreach 循环吗?请指教..”让我们知道它是否有效。
  • 您说您将订单 ID 传递给方法,但出于某种原因将它们与产品 ID 进行比较,这里有问题。

标签: c# mongodb linq


【解决方案1】:

我有包含产品集合的订单集合。

好的,所以你有这样的东西:

var ordersWithTheirProducts = ...
    .Select(... => new Order
    {
         // some Order properties:
         Id = ...
         OrderDate = ...
         ClientId = ...

         // Products of this Order:
         Products = ...
            .Select( product => new Product
            {
                // Several Product properties
                Id = product.Id,
                Name = product.Name,
                Price = product.Price,
                ...
            },
    };

我将一些产品 ID 作为列表传递

IEnumerable<Guid> productIds = ...

我需要返回与输入列表中的任何 id 匹配的产品列表。

因此,您希望选择在您的任何订单中使用的所有产品,并且如果该产品的 Id 是 ProductIds 中的值之一,那么您希望它出现在您的结果中。

首先我们提取您订单中使用的所有产品,然后我们将删除重复项,最后我们仅保留那些在您的 productIds 中具有 Id 的产品:

var result = Orders.SelectMany(order => order.Products)  // extract all Products
    .Distinct()                                           // remove duplicate products
    .Where(product => productIds.Contains(product.Id))
          // keep only those products with an Id that is in productIds

【讨论】:

  • 还有一个问题......如果我需要返回一个带有 orderid 和产品 id 的自定义类而不是整个产品,是否可以在 Linq 中执行此操作?
  • 是的。在Select你看到product =&gt; new Product {...},替换成product =&gt; new MyCustomClass {...},只填写你要获取的属性
  • 其实,这就是我想要使用 LINQ 实现的目标 paste.org/103032
  • 好吧,如果代码是您打算使用的代码,请使用该代码。或者这段代码没有做你想做的事?没有要求,我不能告诉你使用什么代码,可以吗?
【解决方案2】:

遍历输入 guid 将导致每个 guid 的查询。而是发出这样的单个命令:

    var products = collection.AsQueryable()
                     .Where(o => o.Products.Any(p => input.Contains(p.Id)))
                     .SelectMany(o => o.Products)
                     .Where(p => input.Contains(p.Id))
                     .ToList();

首先将带有第一个where 子句的订单列入候选名单。然后使用SelectMany 展开产品。因为,展开整个系列是个坏主意。 unwinding 在服务器内存中创建对象,mongodb 中的管道内存限制为 100mb。

测试程序:

using MongoDB.Entities;
using MongoDB.Entities.Core;
using System;
using System.Linq;

namespace StackOverFlow
{
    public class OrderInfo : Entity
    {
        public Product[] Products { get; set; }
    }

    public class Product
    {
        public Guid Id { get; set; }
    }

    public static class Program
    {
        private static void Main()
        {
            new DB("test-db");

            var input = new[] { Guid.NewGuid(), Guid.NewGuid() };

            var orders = new[] {
                new OrderInfo {  Products = new[] { new Product { Id = input[0] } } },
                new OrderInfo {  Products = new[] { new Product { Id = input[1] } } }
            };

            orders.Save();

            var products = DB.Queryable<OrderInfo>() // collection.AsQueryable() for official driver
                             .Where(o => o.Products.Any(p => input.Contains(p.Id)))
                             .SelectMany(o => o.Products)
                             .Where(p => input.Contains(p.Id))
                             .ToList();
        }
    }
}

【讨论】:

    【解决方案3】:

    先遍历您的订单集合然后检索您的产品会更容易

    public static List<Product> GetProducts(List<int> ids)
    {
        var products = new List<Product>();
        foreach(var order in Orders)
        {
            products.AddRange(order.Products.Where(p => ids.Any(id => id == p.Id)));
        }
    
        return products;
    }
    

    或者干脆

    public static List<Product> GetProducts(List<int> ids)
    {
        return Orders.
            SelectMany(
            o => o.Products
            .Where(p => ids.Any(id => id == p.Id)))
            .ToList();
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 2019-08-29
      • 1970-01-01
      • 2015-04-29
      • 2019-06-09
      相关资源
      最近更新 更多