Skip to content

Commit

Permalink
Add new suggestUser algorithm but not apply yet
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewquang512 committed Nov 27, 2023
1 parent ca9a7f2 commit de9e7dd
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 48 deletions.
194 changes: 149 additions & 45 deletions src/resolvers/Common/suggestUser.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,149 @@
// /**
// * @typedef {string[]} Ids
// */
//
// /**
// *
// * @param {Ids} followingUsers
// followingUsers
// * @param {Ids} similarInterestUsers
// * @param {Ids} similarSkillUsers
// * @param {Ids} user
// */
// export const suggestUser = (followingUsers, similarInterestUsers, similarSkillUsers, user){
// const allUser = getUnion(getUnion(followingUsers, similarInterestUsers), similarSkillUsers))
// const following
// }
//
// /**
// * @see https://en.wikipedia.org/wiki/Jaccard_index
// * @param {Ids} dataset1
// * @param {Ids} dataset2
// */
// const getJaacardIndex = (dataset1, dataset2) => {
// const intersection = getIntersection(dataset1, dataset2)
// const union = getUnion(dataset1, dataset2)
//
// return intersection.length / union.length
// }
//
// /**
// * @param {Ids} dataset1
// * @param {Ids} dataset2
// */
// const getIntersection = (dataset1, dataset2) => {
// return dataset1.filter(value => dataset2.includes(value));
// }
//
//
// /**
// * @param {Ids} dataset1
// * @param {Ids} dataset2
// */
// const getUnion = (dataset1, dataset2) => {
// return [...new Set([...dataset1, ...dataset2])];
// }
/**
* @typedef {object} UserSuggestionConfig
* @property {number} following
* @property {number} interest
* @property {number} skill
*/

/**
* @typedef {object} Category
* @property {string} id
*/

/**
* @typedef {object} Endorsement
* @property {string} id
* @property {string} skillId
*/

/**
* @typedef {object} Following
* @property {UserInfo[]} userFollowing
*/

/**
* @typedef {object} UserInfo
* @property {string} id
* @property {Endorsement[]} endorsements
* @property {Category[]} interestCategories
* @property {Following} followings
*/

export class UserSuggestion {
/**
* @type {UserSuggestionConfig}
*/
_configs = {};

constructor() {
try {
const userSimilarWeight = JSON.parse(process.env.USER_SIMILAR_WEIGHT);
this._configs.following = parseFloat(userSimilarWeight.following);
this._configs.interest = parseFloat(userSimilarWeight.interest);
this._configs.skill = parseFloat(userSimilarWeight.skill);
} catch (error) {
console.error(error);
throw Error('USER_SIMILAR_WEIGHT env is not a valid JSON');
}
}

/**
* @param {UserInfo} currentUser
* @param {UserInfo[]} userList
* @returns {UserInfo[]}
*/
getUserSuggestion = (currentUser, userList) => {
/**
* @type {Map<string, number>}
*/
const similarMap = new Map();

const currUserSkillIds = currentUser.endorsements.map(
(each) => each.skillId,
);
const currUserInterestIds = currentUser.interestCategories.map(
(each) => each.id,
);
const currUserFollowingIds = currentUser.followings.userFollowing.map(
(each) => each.id,
);

userList.forEach((user) => {
// Getting Similar for skill
const userSkillIds = user.endorsements.map((each) => each.skillId);
const skillSimilar = this.getJaacardIndex(currUserSkillIds, userSkillIds);
similarMap.set(user.id, skillSimilar * this._configs.following);

// Getting Similar for interesst
const userInterestIds = user.interestCategories.map((each) => each.id);
const interestSimilar = this.getJaacardIndex(
currUserInterestIds,
userInterestIds,
);
similarMap.set(
user.id,
similarMap.get(user.id) + interestSimilar * this._configs.interest,
);

// Getting Similar for follow
const userFollowingIds = user.followings.userFollowing.map(
(each) => each.id,
);
const followingSimilar = this.getJaacardIndex(
currUserFollowingIds,
userFollowingIds,
);
similarMap.set(
user.id,
(similarMap.get(user.id) + followingSimilar * this._configs.following) *
10,
);
});

const sortedMap = new Map(
[...similarMap.entries()].sort((a, b) => b[1] - a[1]),
);

/**
* @type {UserInfo[]}
*/
const result = [];
sortedMap.forEach((value, key) => {
const foundUser = userList.find((user) => user.id === key);
result.push(foundUser);
});

return result;
};

/**
* @see https://en.wikipedia.org/wiki/Jaccard_index
* @param {Ids} dataset1
* @param {Ids} dataset2
*/
getJaacardIndex = (dataset1, dataset2) => {
if (dataset1.length === 0 || dataset2.length === 0) {
return 0;
}
const intersection = this.getIntersection(dataset1, dataset2);
const union = this.getUnion(dataset1, dataset2);

return intersection.length / union.length;
};

/**
* @param {Ids} dataset1
* @param {Ids} dataset2
*/
getIntersection = (dataset1, dataset2) => {
return dataset1.filter((value) => dataset2.includes(value));
};

/**
* @param {Ids} dataset1
* @param {Ids} dataset2
*/
getUnion = (dataset1, dataset2) => {
return [...new Set([...dataset1, ...dataset2])];
};
}
29 changes: 26 additions & 3 deletions src/resolvers/Query/USER.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import _ from 'lodash';
import { prisma } from '../../prisma/database.js';
import { DEFAULT_LIMIT } from '../../constants.js';
import { UserSuggestion } from '../Common/suggestUser.js';

const userQuery = {
allUsers: async (parent, args, info) => {
Expand Down Expand Up @@ -38,13 +39,35 @@ const userQuery = {
const { after, limit } = args;
const { userId } = args.data;

const currentUser = await prisma.following.findUnique({
const currentUser = await prisma.user.findUnique({
where: {
userId: userId,
id: userId,
},
// include: {
// endorsements: true,
// followings: true,
// interestCategories: true,
// },
});

const [result, count] = await prisma.$transaction([
// const testAll = await prisma.user.findMany({
// where: {
// id: { not: userId },
// isAdmin: 0,
// NOT: {
// id: { in: currentUser.userFollowing },
// },
// },
// include: {
// endorsements: true,
// followings: true,
// interestCategories: true,
// },
// });
// const test = new UserSuggestion();
// const testSuggest = test.getUserSuggestion(currentUser, testAll);

const [result, count] = await Promise.all([
prisma.user.findMany({
where: {
id: { not: userId },
Expand Down

0 comments on commit de9e7dd

Please sign in to comment.