PHP数字图书馆推荐引擎:MySQL关键词无法单字匹配的问题求助
解决PHP数字图书馆推荐引擎的关键词匹配问题
这个问题我做类似推荐功能时也踩过坑!完全匹配整串关键词确实太死板了,咱们改成按单个关键词匹配,只要用户阅读的图书和其他图书有至少一个共同关键词就生成推荐,下面给你两种可行的实现方案:
方案1:直接基于现有关键词字符串字段改造
如果你的图书关键词是存在数据库的keywords字段(比如空格分隔的字符串,像"money investment"),可以通过拆分关键词+构建模糊查询来实现:
步骤1:拆分当前图书的关键词
先把当前图书的关键词拆成单个词的数组,同时去重、过滤空值:
// 假设你用PDO操作数据库,当前图书ID为$currentBookId $currentBookId = 1; $currentBook = $pdo->query("SELECT keywords FROM books WHERE id = {$currentBookId}")->fetch(PDO::FETCH_ASSOC); // 拆分关键词并处理 $rawKeywords = explode(' ', trim($currentBook['keywords'])); $targetKeywords = array_filter(array_unique($rawKeywords)); // 去重+过滤空字符串
步骤2:构建查询条件获取推荐图书
你可以用LIKE多条件组合或者正则表达式来匹配包含任意目标关键词的图书:
方式A:使用LIKE OR条件
// 构建多个LIKE条件,用PDO转义防止SQL注入 $likeConditions = []; foreach ($targetKeywords as $word) { $escapedWord = $pdo->quote($word); $likeConditions[] = "keywords LIKE '%{$escapedWord}%'"; } $likeQuery = implode(' OR ', $likeConditions); // 查询推荐图书,排除当前图书本身 $recommendedBooks = $pdo->query(" SELECT id, title, keywords FROM books WHERE id != {$currentBookId} AND ({$likeQuery}) ")->fetchAll(PDO::FETCH_ASSOC);
方式B:使用正则表达式(更简洁)
// 把关键词转成正则匹配模式,自动转义特殊字符 $regexPattern = implode('|', array_map(function($word) { return preg_quote($word, '/'); }, $targetKeywords)); // 执行查询,加i表示忽略大小写 $recommendedBooks = $pdo->query(" SELECT id, title, keywords FROM books WHERE id != {$currentBookId} AND keywords REGEXP '/{$regexPattern}/i' ")->fetchAll(PDO::FETCH_ASSOC);
方案2:优化数据库结构(推荐长期使用)
如果你的数据量较大,上面的模糊查询可能性能不足,建议把关键词拆分成单独的关联表,这样查询效率更高,也更灵活:
步骤1:创建关键词关联表
CREATE TABLE book_keywords ( book_id INT NOT NULL, keyword VARCHAR(255) NOT NULL, FOREIGN KEY (book_id) REFERENCES books(id), INDEX idx_keyword (keyword) -- 给关键词加索引提升查询速度 );
之后把原books表的关键词拆分,批量插入到这个关联表中(比如"money investment"拆成两条记录:book_id=1, keyword=money和book_id=1, keyword=investment)。
步骤2:查询推荐图书
通过关联表快速匹配有共同关键词的图书:
// 获取当前图书的所有关键词 $stmt = $pdo->prepare("SELECT keyword FROM book_keywords WHERE book_id = ?"); $stmt->execute([$currentBookId]); $targetKeywords = $stmt->fetchAll(PDO::FETCH_COLUMN); // 构建占位符,用预处理防止SQL注入 $placeholders = implode(',', array_fill(0, count($targetKeywords), '?')); $stmt = $pdo->prepare(" SELECT DISTINCT b.id, b.title, b.keywords FROM books b JOIN book_keywords bk ON b.id = bk.book_id WHERE b.id != ? AND bk.keyword IN ({$placeholders}) "); // 执行查询,参数是当前图书ID+目标关键词数组 $stmt->execute(array_merge([$currentBookId], $targetKeywords)); $recommendedBooks = $stmt->fetchAll(PDO::FETCH_ASSOC);
额外优化建议
- 统一大小写:存储和查询关键词时都转成小写(比如用
strtolower()),避免因大小写差异导致匹配失败。 - 过滤停用词:提前过滤掉"the"、"and"这类无意义的停用词,避免生成无关推荐。
- 权重排序:可以给匹配的关键词数量加权,匹配越多的图书排越靠前,提升推荐精准度。
内容的提问来源于stack exchange,提问作者ajejoseph22
相关产品推荐
相关产品推荐

