【问题标题】:Search for products by ship to country按运送到国家/地区搜索产品
【发布时间】:2019-11-15 12:22:31
【问题描述】:

我有一个countries 的表,其中有这个字段:

title: string

我有一个products 的表,其中包含以下字段:

title,
description
...
ship_to: longText

ship_to的格式是这样的,比如一个产品可以发到三个国家,IDs102030

ship_to: {[10,20,30]}

现在,我要做的是按可以运送到的国家/地区过滤产品。因此,例如,我给出了一个包含 10,20(国家 ID)的数组,我想找到至少可以运送到其中一个国家的产品。

但我想不出任何有效的方法。我正在考虑使用 orWhereIn('ship_to', $givenArrayOfCountryIds) 进行 foreach 循环

或类似的东西,但我发现随着时间的推移它会成为这个过滤器查询的瓶颈。

如何修复我的数据库设计,或者可能有一个隐藏的 Laravel 雄辩功能?我找不到任何可以完成这项任务的人。

这是我在意识到这行不通之前写的一段代码:

<?php

namespace App\Model\Filters\Product;

use App\Model\Contracts\AbstractClasses\Filter;

class ShipsTo extends Filter
{
    protected function applyFilter($builder)
    {
        $filterName = $this->filterName();
        $shipsTo = request()->$filterName;
        if ($shipsTo && count($shipsTo) > 0) {
            return $builder->whereHas('countries', function ($query) use ($shipsTo) {
                $query->whereIn('id', $shipsTo);
            });
        }
        return $builder;
    }
}

我使用管道将多个过滤器合二为一。这是调用管道的代码:

public function search($term, $limit)
{
    $builder = Product::select([
        'id', 
        'title',
        'image',
        'price',
        'sale_price'
    ])->active();

    $builder = app(Pipeline::class)
        ->send($builder)
        ->through([
            ShipsTo::class,
        ])
        ->thenReturn();

    return $builder->paginate($limit);
}

【问题讨论】:

标签: php sql laravel


【解决方案1】:

我认为解决它的最佳方法是产品和国家/地区的多对多关系。为了获得它,请在您的数据库上创建一个新表,如下所示:

CREATE TABLE products_countries(
   product_id int not null, /* or the domain of product table primary key */
   country_id int not null, /* or the domain of country table primary key */
   primary key(product_id, country_id),
   FOREIGN KEY (product_id) REFERENCES Product(id), //or the product table primary key
   FOREIGN KEY (country_id) REFERENCES Country(id), //or the product country primary key
)

比产品型号:

public function countries(){
   return $this->belongsToMany('App\Country');
}

比国家模型:

public function products(){
   return $this->belongsToMany('App\Product');
}

【讨论】:

  • 我一开始尝试了这个,但后来意识到如果我有 40k 种产品并且每个产品发送到 200 个不同的国家,那么它就是 200 万行。
  • 使用 SQL 索引会提高效率,缓存也有帮助,我认为这会比循环整个数组更有效,但这是个人意见
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
  • 2013-11-30
  • 1970-01-01
相关资源
最近更新 更多