首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

手把手打造關鍵詞匹配引擎(十七):近義詞多值映射與屬性級別匹配實作

     編輯:PHP 相關知識

手把手打造關鍵詞匹配引擎(十七):近義詞多值映射與屬性級別匹配實作

系列第十七天,繼黑名單後攻克「近義詞/同義詞」模組。面對「同一類目下,不同屬性值對應不同近義詞群」的業務複雜度,設計 category_linklist 表結構、實作 LinklistCharListHandle 策略類、擴展 SelectorItem::getProperties() 介面,完成屬性粒度的近義詞展開。

業務場景:近義詞群組

女裝類目:
- 尺碼:XXL, 加大, 加大碼
- 品類:外套, 衣, 衣服, 外衣, 上衣
- 性別:女款, 女士, 女生, 女性

需求:商品屬性若包含群組內任一詞,自動展開為整組詞,提升搜尋召回率。

一、資料表設計:支援群組與類目隔離

CREATE TABLE `category_linklist` (
    `cid` BIGINT(20) DEFAULT NULL COMMENT '類目ID',
    `catmatch` VARCHAR(50) DEFAULT NULL COMMENT '類目名稱',
    `word` VARCHAR(255) DEFAULT NULL COMMENT '近義詞群,逗號分隔',
    `created` DATETIME DEFAULT NULL COMMENT '錄入時間'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

二、種子資料

INSERT INTO category_linklist (cid, catmatch, word) VALUES
("50010850", "女裝", "XXL,加大,加大碼"),
("50010850", "女裝", "外套,衣,衣服,外衣,上衣"),
("50010850", "女裝", "女款,女士,女生,女性");

三、SelectorItem 擴展:提供屬性陣列介面

<?php
class SelectorItem {
    // ... 既有代碼 ...

    /** 回傳屬性物件陣列:[{id, fieldId, name, value}, ...] */
    public function getProperties() {
        $result = [];
        $props = explode(';', $this->item->props_name); // 如 "1:2:尺碼:XXL;3:4:顏色:紅"
        foreach ($props as $propStr) {
            $result[] = self::createItemProperty(explode(':', $propStr));
        }
        return $result;
    }

    public static function createItemProperty($arr) {
        $obj = new stdClass();
        $obj->id = $arr[0];
        $obj->fieldId = $arr[1];
        $obj->name = $arr[2];
        $obj->value = $arr[3];
        return $obj;
    }
}
?>

四、策略類實作 LinklistCharListHandle

<?php
class LinklistCharListHandle extends CharListHandle {
    public function exec() {
        $sql = "SELECT word FROM category_linklist WHERE cid='{$this->selectorItem->cid}'";
        $linklist = DB::makeArray($sql); // [{word: "XXL,加大,加大碼"}, ...]

        foreach ($linklist as $row) {
            $groupWords = explode(',', $row['word']); // 近義詞群

            // 遍歷商品所有屬性
            foreach ($this->selectorItem->getProperties() as $prop) {
                // 1. 先將原屬性值加入核心詞
                $this->charlist->addCore($prop->value);

                // 2. 若屬性值命中某群組,展開整群
                if (in_array($prop->value, $groupWords)) {
                    foreach ($groupWords as $w) {
                        $this->charlist->addCore($w);
                    }
                }
            }
        }
    }
}
?>

五、Selector 註冊新策略

<?php
class Selector {
    private static $charListHandle = [
        "黑名單" => "BacklistCharListHandle",
        "近義詞" => "LinklistCharListHandle", // 新增
    ];
    // ... 其餘不變
}
?>

代碼評審:為何被於老大「批」?

小帥帥自以為完美,於老大卻直接退回。核心問題預告:

  • 效能:雙重 foreach + in_array,屬性數 × 群組數 × 群組大小,資料量大時極慢。
  • 邏輯缺陷:addCore($prop->value) 在內層迴圈重複呼叫,產生大量重複核心詞。
  • 資料結構:逗號分隔字串難以索引、難以維護「群組元數據」(如群組名、權重)。
  • 擴展性:未來需支援「反義詞」、「修正詞」、「權重加權」等,現有結構難以演進。

下一回將揭曉於老大的優化方案:倒排索引、預計算、緩存策略與領域模型重構。


近義詞看似簡單的「多值映射」,實則考驗資料結構設計、演算法效能與領域建模能力。本回完成 MVP 實作,暴露出 naïvely 實作的典型問題,為後續架構升級鋪墊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved