Activity Streams/Primer/Representing Relationships Between Entities

From W3C Wiki

Copied from Representing Relationships Between Entities

The Relationship object is used to represent relationships between individuals. It can be used, for instance, to describe that one person is a friend of another, or that one person is a member of a particular organization. The intent of modeling Relationship in this way is to allow descriptions of activities that operate on the relationships in general, and to allow representation of Collections of relationships.

For instance, many social systems have a notion of a "friends list". These are the collection of individuals that are directly connected within a person's social graph. Suppose we have a user, Sally, with direct relationships to users Joe and Jane. Sally follows Joe's updates while Sally and Jane have a mutual relationship.

Using the Relationship object, we can model these relationships as:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "Sally's friends list",
  "type": "Collection",
  "items": [
    {
      "summary": "Sally is influenced by Joe",
      "type": "Relationship",
      "subject": {
        "type": "Person",
        "name": "Sally"
      },
      "relationship": "http://purl.org/vocab/relationship/influencedBy",
      "object": {
        "type": "Person",
        "name": "Joe"
      }
    },
    {
      "summary": "Sally is a friend of Jane",
      "type": "Relationship",
      "subject": {
        "type": "Person",
        "name": "Sally"
      },
      "relationship": "http://purl.org/vocab/relationship/friendOf",
      "object": {
        "type": "Person",
        "name": "Jane"
      }
    }
  ]
}

The relationship property specifies the kind of relationship that exists between the two individuals identified by the subject and object properties. Used together, these three properties form what is commonly known as a "<a href="http://patterns.dataincubator.org/book/reified-statement.html">reified statement</a>" where subject identifies the subject, relationship identifies the predicate, and object identifies the object.

While use of reified statements can be problematic and confusing in certain situations, their use within the Activity Streams vocabulary to describe relationships provides a straightforward mechanism of describing changes to an individual's social graph. For instance, to indicate that Sally has created a new relationship to user Matt, an implementer can use the Relationship object together with the Create activity:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "Sally became a friend of Matt",
  "type": "Create",
  "actor": "http://sally.example.org",
  "object": {
    "type": "Relationship",
    "subject": "http://sally.example.org",
    "relationship": "http://purl.org/vocab/relationship/friendOf",
    "object": "http://matt.example.org",
    "startTime": "2015-04-21T12:34:56"
  }
}

Additionally, modeling the relationship in this way allows implementers to articulate additional properties of the relationship itself. For instance, the date and time at which the relationship began or ended.

Implementations may reuse existing vocabularies that have been developed for the purpose of describing relationships, or create their own guided by requirements of their particular implementation. Existing vocabularies include the "Friend of a Friend" and "Relationship" vocabularies.

Modeling "friend requests"

One common use case for many social platforms is the establishment of symmetrical "friend" relationships, in which one user initially extends a request to another user to establish a new connection. Once the connection is made, both users automatically begin receiving notifications about activities performed by the other, and the established relationship becomes visible in either user's "friends list".

The initial "friend request" can be modeled by composing the Offer and Relationship object types as in the following example:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "http://example.org/connection-requests/123",
  "summary": "Sally requested to be a friend of John",
  "type": "Offer",
  "actor": "acct:sally@example.org",
  "object": {
    "summary": "Sally and John's friendship",
    "id": "http://example.org/connections/123",
    "type": "Relationship",
    "subject": "acct:sally@example.org",
    "relationship": "http://purl.org/vocab/relationship/friendOf",
    "object": "acct:john@example.org"
  },
  "target": "acct:john@example.org"
}

Assuming the "friend request" is accepted, the remaining steps in this common application scenario can be represented as a set of distinct activities:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "Sally and John's relationship history",
  "type": "Collection",
  "items": [
    {
      "summary": "John accepted Sally's friend request",
      "id": "http://example.org/activities/122",
      "type": "Accept",
      "actor": "acct:john@example.org",
      "object": "http://example.org/connection-requests/123",
      "inReplyTo": "http://example.org/connection-requests/123",
      "context": "http://example.org/connections/123",
      "result": [
        "http://example.org/activities/123",
        "http://example.org/activities/124",
        "http://example.org/activities/125",
        "http://example.org/activities/126"
      ]
    },
    {
      "summary": "John followed Sally",
      "id": "http://example.org/activities/123",
      "type": "Follow",
      "actor": "acct:john@example.org",
      "object": "acct:sally@example.org",
      "context": "http://example.org/connections/123"
    },
    {
      "summary": "Sally followed John",
      "id": "http://example.org/activities/124",
      "type": "Follow",
      "actor": "acct:sally@example.org",
      "object": "acct:john@example.org",
      "context": "http://example.org/connections/123"
    },
    {
      "summary": "John added Sally to his friends list",
      "id": "http://example.org/activities/125",
      "type": "Add",
      "actor": "acct:john@example.org",
      "object": "http://example.org/connections/123",
      "target": {
        "type": "Collection",
        "summary": "John's Connections"
      },
      "context": "http://example.org/connections/123"
    },
    {
      "summary": "Sally added John to her friends list",
      "id": "http://example.org/activities/126",
      "type": "Add",
      "actor": "acct:sally@example.org",
      "object": "http://example.org/connections/123",
      "target": {
        "type": "Collection",
        "summary": "Sally's Connections"
      },
      "context": "http://example.org/connections/123"
    }
  ]
}

As illustrated in this example, accepting the "friend request" results in four additional activities including: John following Sally, Sally following John, John adding the relationship with Sally to his collection of Connections, and Sally adding the relationship with John to her collection of Connections.

In this example,

  1. The optional result property is used within the Accept activity to identify the additional activities that occurred as a result of the accept.
  2. The optional context property is used to relate the various activities back to a common reference point, which in this example is the relationship being established. The context allows an implementation to efficiently group related activities together for display or analytic purposes.