如何在 Laravel 中明智地获取产品类别?

Posted

技术标签:

【中文标题】如何在 Laravel 中明智地获取产品类别?【英文标题】:How to get products category wise in Laravel? 【发布时间】:2021-10-08 13:32:15 【问题描述】:

here 提出了类似的问题。

我正在研究 API。我的产品表包含一万多个不同类别的产品。我需要减少查询执行时间,因此为此,我必须修改一个 API,该 API 将仅获取每个类别的 20 个产品,并将整个 API 响应按类别分组。 API 响应如下所示。


"data": 
"products": 
  "Beauticians & Style": [
    
      "Title": "Product A",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product B",
      "Price": "0.00",
      "DiscountPrice": 0
    
  ],
  "Groceries": [
    
      "Title": "Product G",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product R",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product O",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product C",
      "Price": "0.00",
      "DiscountPrice": 0
    
  ],
  "Women's Fashion": [
    
      "Title": "Product W",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product O",
      "Price": "0.00",
      "DiscountPrice": 0
    ,
    
      "Title": "Product M",
      "Price": "0.00",
      "DiscountPrice": 0
    
  ]


控制器

$products = Category::with('products', function($q)
    $q->take(20);
)->get();

类别模型

class Category extends Model

    use HasFactory;

    public function products()
    
        return $this->hasMany('App\Models\Product', 'CategoryID', 'CategoryID');
    

我试过了,但没有得到确切的结果。

【问题讨论】:

【参考方案1】:

当访问 Eloquent 关系作为属性时,相关模型是“延迟加载”这意味着在您第一次访问该属性之前不会实际加载关系数据。

解决方法,你可以使用:

$products = Category::with('products')
    ->get()
    ->map(function ($query) 
        $query->setRelation('products', $query->products->take(20));
        return $query;
    );

参考:

"This is not a bug, it's a limitation"

更新

OP 评论:

但在这种情况下,我们获取所有 10k 个产品,然后在集合上设置关系

是的,这是性能问题,但是,您的问题是关于 eadger。 This is limitation

Eloquent 作为工具,而不是解决方案。它只是 SQL 的一个包装器。如果您想将每个类别的产品数量限制为(n),则查询会变得复杂。

要解决此问题,您需要使用window function:

SELECT * 
FROM (
    SELECT
        *, 
        ROW_NUMBER() OVER (PARTITION BY `category_id`) AS row_num 
    FROM `products`
) AS temp_table 
WHERE row_num <= 10 
ORDER BY row_num

或者,您可以使用this Laravel Eloquent extension 来允许使用窗口函数限制每个父级的急切加载结果的数量。

类别模型

use Staudenmeir\EloquentEagerLimit\HasEagerLimit;
use App\Models\Product;

class Category extends Model

    use HasEagerLimit;

    public function products()
    
        return $this->hasMany(Product::class);
    

产品型号

use Staudenmeir\EloquentEagerLimit\HasEagerLimit;

class Product extends Model

    use HasEagerLimit;

试试

$products = Category::with(['products' => function ($query) 
    $query->latest()->limit(20);
])->get();

这对你解释够了吗?

【讨论】:

但在这种情况下,我们正在获取所有 10k 产品,然后在集合上设置关系。【参考方案2】:

如果每个产品只有一个类别,您的表格结构必须如下:

products
    id
    ...
    category_id
categories
    id
    ...

并且您在 Category 中的产品关系必须如下:

class Category extends Model

    use HasFactory;
    public function products()
    
        return $this->hasMany(App\Models\Product::class);
    

并将您的控制器更改为:

$products = Category::with('products', function($q)
            $q->take(20);
        )->get();

【讨论】:

以上是关于如何在 Laravel 中明智地获取产品类别?的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql中找到客户明智类别中的最大产品ID?

如何在类别中创建 UITableViewCell 明智地排列 JSON 对象

分类明智的产品销售 laravel

在 NextJs 中如何使用更改事件更改 getServerSideProps

IoT创业:产品雷达图 - 如何明智地权衡产品?

如何在laravel中获取多对多关系项