123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import { CloudObject, CloudQuery } from "./ncloud";
- export class RecommendationService {
- private perferQuery: CloudQuery; // 偏好查询对象
- constructor() {
- this.perferQuery = new CloudQuery('Perfer'); // 偏好数据存储在 perfer 类中
- }
- /**
- * 获取用户的物品推荐
- * @param userId 用户ID
- * @param howMany 推荐数量
- * @returns 推荐的物品ID列表
- */
- public async getItemRecommendations(userId: string, howMany: number): Promise<string[]> {
- // 获取用户的偏好数据
- const userPreferences = await this.getUserPreferences(userId);
-
- if (!userPreferences || userPreferences.length === 0) {
- return [];
- }
- // 计算物品相似度
- //console.log(userPreferences);
- const similarItems = await this.calculateItemSimilarity(userPreferences);
- // 获取推荐物品
- return this.getTopRecommendations(similarItems, howMany);
- }
- /**
- * 获取用户的偏好数据
- * @param userId 用户ID
- * @returns 用户偏好物品的列表
- */
- private async getUserPreferences(userId: string): Promise<CloudObject[]> {
- this.perferQuery.equalTo('user_id', userId); // 查询条件
- const preferences = await this.perferQuery.find(); // 获取用户的偏好数据
- console.log(preferences);
- return preferences; // 返回用户偏好物品列表
- }
- /**
- * 计算物品相似度
- * @param userPreferences 用户偏好物品
- * @returns 物品相似度的映射
- */
- private async calculateItemSimilarity(userPreferences: CloudObject[]): Promise<Map<string, number>> {
- const itemSimilarity: Map<string, number> = new Map();
- // 遍历用户偏好物品,计算与其他物品的相似度
- for (const pref of userPreferences) {
-
- const itemId = pref.get('item_id');
- const preferenceValue = pref.get('perference');
- //console.log(`${itemId} : ${preferenceValue}`);
- // 获取所有物品的偏好数据
- const allPreferences = await this.perferQuery.find();
- for (const otherPref of allPreferences) {
- const otherItemId = otherPref.get('item_id');
- const otherPreferenceValue = otherPref.get('perference');
- //console.log(`${otherItemId} : ${otherPreferenceValue}`);
- if (itemId !== otherItemId) { // 排除自身
- console.log(`${itemId} : ${preferenceValue}`)
- console.log(`${otherItemId} : ${otherPreferenceValue}`);
- const similarityScore = this.computeSimilarity(preferenceValue, otherPreferenceValue);
- console.log(`${itemId} : ${similarityScore}`);
- itemSimilarity.set(otherItemId, (itemSimilarity.get(otherItemId) || 0) + similarityScore);
- }
- }
- }
- return itemSimilarity;
- }
- /**
- * 计算两个物品之间的余弦相似度
- * @param preference1 第一个物品的偏好值
- * @param preference2 第二个物品的偏好值
- * @returns 相似度分数
- */
- private computeSimilarity(preference1: number, preference2: number): number {
- // 计算点积
- const dotProduct = preference1 * preference2;
- // 计算模
- const magnitude1 = Math.sqrt(preference1 ** 2);
- const magnitude2 = Math.sqrt(preference2 ** 2);
- // 计算余弦相似度
- if (magnitude1 === 0 || magnitude2 === 0) {
- return 0; // 避免除以零的情况
- }
- return dotProduct / (magnitude1 * magnitude2);
- }
- /**
- * 获取前 N 个推荐物品
- * @param similarItems 物品相似度映射
- * @param howMany 推荐数量
- * @returns 推荐物品ID列表
- */
- private getTopRecommendations(similarItems: Map<string, number>, howMany: number): string[] {
- // 将相似度映射转换为数组并排序
- const sortedItems = Array.from(similarItems.entries()).sort((a, b) => b[1] - a[1]);
- // 获取前 N 个物品ID
- return sortedItems.slice(0, howMany).map(item => item[0]);
- }
- }
|