3

I have orders collection that contains products collection.I'm passing some product ids as list to the method.I need to return a list of products matching with any of the id in the input list.

Do i need to use a foreach loop like this? Please advice ..

   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));
      }

    }

Update: enter image description here

Update2: enter image description here

Update 3: I pass product Ids and i need to get list of products from orders that match the product Ids.

4

3 回答 3

1

遍历输入 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();
        }
    }
}

于 2020-02-05T03:11:04.710 回答
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 中的值之一,那么您希望它出现在您的结果中。

首先,我们提取您的订单中使用的所有产品,然后我们将删除重复项,最后我们仅保留那些在您的 productId 中具有 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
于 2020-02-05T13:26:06.037 回答
0

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

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();
}
于 2020-02-04T12:47:49.463 回答