Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Collection (Products) of Objects for each item in a list

Tags:

c#

linq

mongodb

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.

like image 650
techno Avatar asked Nov 26 '25 04:11

techno


2 Answers

I have orders collection that contains products collection.

Okay, so you have something like this:

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,
                ...
            },
    };

I'm passing some product ids as list

IEnumerable<Guid> productIds = ...

I need to return a list of products matching with any of the id in the input list.

So, you want to select all Products that were used in any of your Orders, and if that Product has an Id that is one of the values in ProductIds, then you want it in your result.

First we extract all Products that are used in your Orders, then we'l remove the Duplicates, and finally we keep only those Products that have an Id in your productIds:

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
like image 76
Harald Coppoolse Avatar answered Nov 27 '25 16:11

Harald Coppoolse


iterating over the input guids will cause a query per each guid. instead issue a single command like this:

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

first shortlist the orders with the first where clause. and then unwind the products with SelectMany. because, unwinding the whole collection is a bad idea. unwinding creates objects in server memory and there's a pipeline memory limit of 100mb in mongodb.

test program:

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();
        }
    }
}
like image 40
Dĵ ΝιΓΞΗΛψΚ Avatar answered Nov 27 '25 17:11

Dĵ ΝιΓΞΗΛψΚ



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!