本文可作为redis in action第七章的读书笔记
public void addJob(Jedis conn, String jobId, String... requiredSkills) {
conn.sadd("job:" + jobId, requiredSkills);
}
@SuppressWarnings("unchecked")
public boolean isQualified(Jedis conn, String jobId, String... candidateSkills) {
String temp = UUID.randomUUID().toString();
Transaction trans = conn.multi();
for(String skill : candidateSkills) {
trans.sadd(temp, skill);
}
trans.expire(temp, 5);
trans.sdiff("job:" + jobId, temp);
List
测试代码:
public class Chapter07Test {
static Jedis conn = null;
static Chapter07 c=null;
@BeforeClass
public static void initConn(){
System.out.println("test before");
conn = new Jedis("10.150.0.80");
conn.auth("dlf123123");
c=new Chapter07();
}
@Test
public void testIsQualifiedForJob() {
System.out.println("\n----- testIsQualifiedForJob -----");
c.addJob(conn, "test", "q1", "q2", "q3");
//返回true
System.out.println(c.isQualified(conn, "test", "q1", "q3", "q2","q4"));
//返回false
System.out.println(c.isQualified(conn, "test", "q1", "q2"));
}
}
OK,上面的代码能正常运行 那么有问题么?
member是职位 score是这个职位需要的技能的数量
首先将职位与技能添加到库里
public void indexJob(Jedis conn, String jobId, String... skills) {
Transaction trans = conn.multi();
Set unique = new HashSet();
for (String skill : skills) {
trans.sadd("idx:skill:" + skill, jobId);
unique.add(skill);
}
// 记录每个职位需要的技能数量
trans.zadd("idx:jobs:req", unique.size(), jobId);
trans.exec();
}
好了,我们现在先不看代码了,先说说我们得了解的redis的几个命令
public Set findJobs(Jedis conn, String... candidateSkills) {
String[] keys = new String[candidateSkills.length];
double[] weights = new double[candidateSkills.length];
for (int i = 0; i < candidateSkills.length; i++) {
keys[i] = "skill:" + candidateSkills[i];
weights[i] = 1.0;
}
Transaction trans = conn.multi();
//这里的idx:jobScores
//member是职位 score是我能满足这个职位的技能的数量
//这里面是所有跟我还有点"关系"的职位
//国务院总理这个职位所要求的技能 我一个都没有
//那么 这个idx:jobScores里肯定就没有国务院总理这个职位
String jobScores = zunion(
trans, 100, new ZParams().weightsByDouble(weights), keys);
System.out.println("jobscores: zrange idx:"+jobScores+" 0 -1 withscores");
// 用需要的技能数 减去我现在有的技能数
String finalResult = zintersect(
trans, 100, new ZParams().weightsByDouble(-1, 1), jobScores, "jobs:req");
System.out.println("jobscores: zrange idx:"+finalResult+" 0 -1 withscores");
trans.exec();
return conn.zrangeByScore("idx:" + finalResult, 0, 0);
}
public String zintersect(Transaction trans, int ttl,
ZParams params, String... sets){
return zsetCommon(trans, "zinterstore", ttl, params, sets);
}
public String zunion(Transaction trans, int ttl,
ZParams params, String... sets) {
return zsetCommon(trans, "zunionstore", ttl, params, sets);
}
//把zunionstore和zinterstore提取出来
//使用反射技术 不懂的自己去看反射
//这里产生的中间数据 都不必一直保存 所有有个ttl
private String zsetCommon(Transaction trans, String method, int ttl,
ZParams params, String... sets) {
String[] keys = new String[sets.length];
for (int i = 0; i < sets.length; i++) {
keys[i] = "idx:" + sets[i];
}
String id = UUID.randomUUID().toString();
try{
Method m=trans.getClass().getDeclaredMethod(method, String.class,
ZParams.class, String[].class);
System.out.println("method: "+method);
m.invoke(trans,"idx:" + id, params, keys);
}catch(Exception e){
throw new RuntimeException(e);
}
trans.expire("idx:" + id, ttl);
return id;
}
再看看测试代码:
@Test
public void testIndexAndFindJobs() {
System.out.println("\n----- testIndexAndFindJobs -----");
c.indexJob(conn, "test1", "q1", "q2", "q3");
c.indexJob(conn, "test2", "q1", "q3", "q4");
c.indexJob(conn, "test3", "q1", "q3", "q5");
// System.out.println(c.findJobs(conn, "q1").size());
Iterator result =null;
// result=c.findJobs(conn, "q1", "q3", "q4").iterator();
// printIterator(result);
result = c.findJobs(conn, "q1", "q3", "q5").iterator();
printIterator(result);
result = c.findJobs(conn, "q8", "q9", "q310", "q11", "q12").iterator();
printIterator(result);
}
测试结果:
test before
abc