手机配件(1)
├─ 耳机(2)
│ └─ 蓝牙耳机(3)
└─ 移动电源(4)
现在我们再来逐一分析几个场景:
场景一,查询『蓝牙耳机』的所有祖先类目:取出 path 字段的值 -1-2-,以 - 为分隔符分割字符串并过滤掉空值,得到数组 [1, 2] ,然后使用 Category::whereIn('id', [1, 2])->orderBy('level')->get() 即可获得排好序的所有父类目。
场景二,查询『手机配件』的所有后代类目:取出自己的 path 值 -,然后追加上自己的 ID 字段得到 -1-,然后使用 Category::where('path', 'like', '-1-%')->get() 即可获得所有后代类目。
场景三,判断『移动电源』与『蓝牙耳机』是否有祖孙关系:取出两者中 level 值较大的类目『蓝牙耳机』的 path 值 -1-2- 并赋值给变量 $highLevelPath,取另外一个类目的 path 值并追加该类目的 ID 得 -1-4- 并赋值给变量 $lowLevelPath,然后只需要判断变量 $highLevelPath 是否以 $lowLevelPath 开头,如果是则有祖孙关系。
可以看到我们通过新增一个冗余的 path 字段,就能很好地解决性能问题,这是一种很典型的(存储)空间换(执行)时间策略。