Как моделировать социальный граф в Java - PullRequest
4 голосов
/ 26 января 2010

Очень простой сценарий

N пользователей, каждый пользователь может иметь 0 .. N - 1 друзей (которые также являются пользователями)

Как мне смоделировать это в Java для хранилища данных AppEngine

Сценарий для рассмотрения

  • пользователь x и пользователь y становятся друзьями (поэтому обоим нужно обновить свой статус в транзакции

Ответы [ 2 ]

7 голосов
/ 26 января 2010

Мы смоделировали отношения пользователя как простую сущность 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 должна быть довольно простой.

0 голосов
/ 26 января 2010

Рассмотрите возможность использования таблицы Friendship с двумя внешними ключами, user1 и user2. Запись в этой таблице моделирует социальную связь между двумя пользователями. Вы могли бы даже добавить больше столбцов, чтобы описать type этого социального отношения.

(или рассмотрите ответ sfussenegger;) та же идея, но лучшая презентация)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...