我在设计用于推文分析的系统时需要建议。
目标:对于给定的主题标签,找出与其他哈希标签共现的频率。找出每小时模式。我们应该能够回答这种格式的查询:对于给定日期(例如2013年4月13日)和给定的一小时时间段(比如说下午3:00-4:00),前5个共同发生的是什么带有“#iPhone”的#标签。
我的方法:我使用“twitter4j”liabrary来访问Twitter数据。我可以查询并获得100个推文进行一次通话(Twitter仅允许那些多个推文)。我可以提取时间和其他相关数据。我计划有一个线程,每隔5分钟就会查询一下twitter。这是针对观察者的每小时模式。这是我被击中的地方:我应该如何将这些信息存储在数据库中?我应该维护一个带有键值的hashmap,以及使用“#iPhone”发生频率的值。或者我应该将未聚合的数据直接存储在数据库中?查询“twitter”到观察者每小时模式的最佳方法是什么?我应该将时间以“epoch”格式存储在DB中,还是作为日期一列和小时存储在DB中的另一列中?
非常感谢您的宝贵意见。
答案 0 :(得分:2)
我建议您使用the Streaming API in Twitter。这将允许您保持与Twitter的持久HTTP连接,以便您可以搜索推文。 Twitter推荐使用Streaming API推文分析类型应用程序。
但您必须预处理某些数据,以便分析更快。另请查看twitter4j's inherent Streaming API支持。
有关示例,请查看以下Github code。
答案 1 :(得分:1)
如ay89所说,使用key-tag和value-freq,在存储到DB之前聚合,并使用纪元。
此外,由于这是一个多线程程序,因此您有两种同步选项:
选项1是使用ConcurrentHashMap。当聚合器运行时,它将使用:
(for Key key : hashMap.keySet()) {
Database.save(key, hashMap.get(key));
hashMap.replace(key, 0);
}
换句话说,在将标记写入数据库后将其设置为0。添加推文数据的方法将使用
public void increment(Key key) {
boolean done = false;
while(!done) {
int current = hashMap.get(key);
int newValue = current + 1;
done = hashMap.replace(key, current, newValue);
}
}
这是一种增加频率的线程安全方法。
选项2可能更有意义。您的聚合器将使用新实例替换hashmap。
class DataStore {
Map map = new HashMap();
public void add(Key key, Value value) {
// called by the method querying tweet data
}
public void aggregate() {
// called by the aggregator thread every five minutes
Map oldMap = map;
map = new HashMap();
DataBase.save(oldMap);
}
}
最重要的是,当聚合器将其保存到数据库时,您不希望以不受控制的方式修改散列映射。第二个选项更简单,因为它只是为查询线程创建一个新的hashmap,而聚合器将旧的hashmap保存到数据库中。
答案 2 :(得分:0)
因为您只需要检索频率,最好将其存储在散列(key-tag,value-freq)中,因为存储在db中的非聚合数据会占用更多空间(并且主要用于不是必要的)最终你必须稍后聚合。
纪元时间是存储时间的好方法。因为你可以根据时区使用它进行本地化,如果以后需要的话。