package sample.save2dropbox.business; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import java.util.Timer; import java.util.TimerTask; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import redis.clients.jedis.Jedis; import rfx.server.configs.NoSqlServerInfoConfigs; import rfx.server.util.SocialAnalyticsUtil; import rfx.server.util.StringUtil; import rfx.server.util.Utils; import sample.save2dropbox.model.Item; import com.google.gson.Gson; /** * @author trieu * * the recommend items, the core idea is, modeling interest's user by using most used keywords from past to current * */ public class UserRecommender { static String redisHost = NoSqlServerInfoConfigs.getServerInfo("REDIS_SERVER1").host; static int redisPort = NoSqlServerInfoConfigs.getServerInfo("REDIS_SERVER1").port; static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) { SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>( new Comparator<Map.Entry<K,V>>() { @Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) { int res = (-1)*e1.getValue().compareTo(e2.getValue()); return res != 0 ? res : 1; // preserve items with equal values } } ); sortedEntries.addAll(map.entrySet()); return sortedEntries; } public static List<String> getTopKeywordsOfUser(int userId){ String host = NoSqlServerInfoConfigs.getServerInfo("REDIS_SERVER1").host; int port = NoSqlServerInfoConfigs.getServerInfo("REDIS_SERVER1").port; Jedis jedis = new Jedis(host, port); Map<String, String> map = jedis.hgetAll("user:" + userId); jedis.close(); ConcurrentHashMap<String, Integer> userKeywordStats = new ConcurrentHashMap<>(); map.values().parallelStream().forEach((String json)->{ try { //System.out.println(json); Item item = new Gson().fromJson(json, Item.class); if(item.getKeywords() == null){ return; } List<String> keywords = item.getKeywords(); for (String keyword : keywords) { keyword = keyword.trim(); if(!keyword.isEmpty()){ int kf = userKeywordStats.getOrDefault(keyword, -1); if(kf < 0){ kf = 1; userKeywordStats.put(keyword, kf); } else { kf++; userKeywordStats.put(keyword, kf); } } //System.out.println(keyword+" -> " + kf); } } catch (Exception e) { } }); //System.out.println(userKeywordStats); int top = 5; SortedSet<Entry<String, Integer>> sortedset = entriesSortedByValues(userKeywordStats); List<String> top5Keywords = new ArrayList<String>(top); for (Entry<String, Integer> entry : sortedset) { //System.out.println(entry.getKey()+" => "+entry.getValue()); top5Keywords.add(entry.getKey()); top--; if(top <= 0){ break; } } return top5Keywords; } public static List<Item> recommendItems(int userId){ List<String> dnaUser = getTopKeywordsOfUser(userId); return SearchEngineLucene.searchItemsByKeywords(dnaUser,userId); } public static void computeRecomendedItemsForUser(int userId){ List<Item> items = SearchEngineLucene.searchItemsByKeywords(getTopKeywordsOfUser(userId),userId); Jedis jedis = new Jedis(redisHost, redisPort); items.stream().forEach((Item item)->{ System.out.println(item.getLink()); int fbLike = SocialAnalyticsUtil.getFacebookLikeCount(item.getLink()); System.out.println(fbLike); String recKey = "user:" + item.getUser_id() + " post:" + item.getPost_id(); jedis.zadd("recommend:"+userId, fbLike, recKey);//user:55455908 post:18 }); jedis.close(); } public static void fullIndexingItems(){ Jedis jedis = new Jedis(redisHost, redisPort); Set<String> userKeys = jedis.keys("user:*"); userKeys.stream().forEach((String userkey)->{ Map<String, String> map = jedis.hgetAll(userkey); System.out.println("indexing items of user " + userkey + " itemCount "+map.size()); List<Item> userItems = new ArrayList<>(); map.values().stream().forEach((String json)->{ String k = ""; int user_id = StringUtil.safeParseInt(userkey.replace("user:", "")); try { Item item = new Gson().fromJson(json, Item.class); item.setUser_id(user_id); //jedis.hget(KEY_INDEXED_ITEMS, item.) k = "p:"+item.getPost_id(); System.out.println(" item " + k); String v = jedis.hget(KEY_INDEXED_ITEMS, k); if(v == null) { userItems.add(item); System.out.println("INDEXED "+k); jedis.hset(KEY_INDEXED_ITEMS, k,"1"); } } catch (Exception e) { System.err.println(e.getMessage() + " at k: " + k); } }); SearchEngineLucene.indexItems(userItems); }); jedis.close(); Utils.sleep(500); userKeys.stream().forEach((String userkey)->{ int userId = StringUtil.safeParseInt(userkey.replace("user:", "")); computeRecomendedItemsForUser(userId ); }); Utils.sleep(500); } static final String KEY_INDEXED_ITEMS = "indexed-items"; public static void scheduleJob(){ Timer scheduledService = new Timer(true);//daemon process TimerTask autoTask = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub fullIndexingItems(); } }; long delay = 1; long period = 15; scheduledService.schedule(autoTask , delay *1000L, period*1000L); } public static void main(String[] args) { //int userId = 47579516; //System.out.println(getTopKeywordsOfUser(userId)); // List<Item> items = UserRecommender.recommendItems(userId); // for (Item item : items) { // System.out.println(item); // } scheduleJob(); while (true) { Utils.sleep(1000); } //computeRecomendedItemsForUser(userId); //fullIndexingItems(); } //issue: remove duplicated keywords: CSS and css is the same }