非常简单的场景
N个用户,每个用户可以有0 ... N - 1个朋友(也是用户)
如何在AppEngine数据存储的 Java 中对此进行建模
要考虑的场景
答案 0 :(得分:7)
我们将用户关系建模为一个简单的UserRelation实体:
class UserRelation {
User _from;
User _to;
RelationState _state;
}
其中RelationState是一个枚举,描述状态(通常,不仅仅是友谊)
enum RelationState {
BLOCKED, NONE, PENDING_FRIEND, FRIEND;
}
实际上,我们也使用此枚举来进行授权,例如在用户档案上。
enum RelationState implements IRole {
BLOCKED, NONE(BLOCKED), PENDING_FRIEND(NONE), FRIEND(PENDING_FRIEND);
private final List<IRole> _impliedRoles;
private final List<String> _roleStrings;
private RelationState(final IRole... impliedRoles) {
HashSet<IRole> set = new HashSet<IRole>();
for (final IRole impliedRole : impliedRoles) {
set.add(impliedRole);
set.addAll(impliedRole.getImpliedRoles());
}
_impliedRoles = Collections.unmodifiableList(new ArrayList<IRole>(set));
ArrayList<String> list = new ArrayList<String>(getImpliedRoles().size() + 1);
list.add(getName());
for (final IRole implied : getImpliedRoles()) {
list.add(implied.getName());
}
_roleStrings = Collections.unmodifiableList(list);
}
public List<IRole> getImpliedRoles() {
return _impliedRoles;
}
public String getName() {
return name();
}
public boolean hasRole(final IRole role) {
return this == role || _impliedRoles.contains(role);
}
public List<String> getRoleStrings() {
return _roleStrings;
}
}
public interface IRole {
public List<? extends IRole> getImpliedRoles();
public String getName();
public boolean hasRole(final IRole role);
public List<String> getRoleStrings();
}
对于每个(对称)关系(例如,在facebook上使用的友谊)和对于非对称关系的仅一个对象(例如在推特上使用的关注者或被阻止的用户),最容易具有两个对象。虽然这可能看起来像开销,但使用两个对象肯定会简化查询。
我认为AppEngine部分本身应该非常简单。
答案 1 :(得分:0)
考虑使用仅包含两个外键Friendship
和user1
的{{1}}表。此表中的条目模拟两个用户之间的社交连接。您甚至可以添加更多列来描述此社交关系的user2
。
(或考虑sfussenegger的答案;)相同的想法,但更好的介绍)