I want to sort products by inventory

I want to sort products by inventory and getting inventory by lookup so at next line of inventoryLevellookup i got a property of inventory name and in this array i want to sum item and sort it by sum result

[
          { $match: filter },
          { $lookup: inventoryLevelLookup },
          { $sort: sortingFilter },
          {
            $facet: {
              products: [
                { $skip: startIndex },
                { $limit: limit },
                { $lookup: variantsLookup },
              ],
              count: [{ $count: 'totalCount' }],
            },
          },
          { $project: fields },
        ];

Please provide sample documents in JSON format so that we can cut-n-paste into our test systems.

Also provide sample results.

You are using a lot of variables, it will be nice to see values that supports you sample results.

1 Like
try {
    const allVendors = await Product.find(allVendorsFilter, {
      vendor: 1,
      _id: 0,
    });
    const variantsLookup = {
      from: 'variants',
      localField: 'shopifyProductId',
      foreignField: 'shopifyProductId',
      as: 'variant',
    };
    const inventoryLevelLookup = {
      from: 'inventorylevels',
      localField: 'variant.shopifyInventoryItemId',
      foreignField: 'shopifyInventoryItemId',
      as: 'inventory',
    const pipeline = [
      { $match: filter },
      { $sort: sortingFilter },
      {
        $facet: {
          products: [
            { $skip: startIndex },
            { $limit: limit },
            { $lookup: variantsLookup },
            { $lookup: inventoryLevelLookup },
          ],
          count: [{ $count: 'totalCount' }],
        },
      },
      { $project: fields },
    ];
    // aggregation result is always array with 1 index, destructured that
    let [result] = await Product.aggregate(pipeline)
      .collation({
        locale: 'en',
        numericOrdering: true,
      })
      .allowDiskUse(true);
    let { count, products } = result;
    const totalCount = count.length > 0 ? count[0].totalCount : 0;
    // to replace inventory array of products with inventory object having totalVariants & totalStock
    for (let i = 0; i < products.length; i++) {
      products[i].inventory = {
        totalVariants: products[i].inventory.length,
        totalStock: products[i].inventory.reduce(
          (prev, current) => prev + current.available,
          0
        ),
        items: products[i].inventory,
      };
    }
    return Promise.resolve({
      data: { products, totalCount, allVendors },
  } catch (e) {
    return Promise.reject(e.message);
  }

Sorry but in the absence of

and

and some values for

like filter, sortingFilter, startIndex, …, working on this use-case is a completely waste of time for me. Hopefully, for you, someone with more time will pickup your issue.

1 Like