Skip to main content

Following Query

Query the social graph to find who an account follows and who follows them.

Query Structure​

query GetFollowing(
$account_id: String!
$limit: Int
$offset: Int
) {
following(
where: { follower_id: { _eq: $account_id } }
limit: $limit
offset: $offset
) {
id
follower_id
follower {
label
image
}
following_id
following {
label
image
}
created_at
}
following_aggregate(where: { follower_id: { _eq: $account_id } }) {
aggregate {
count
}
}
}

Variables​

{
"account_id": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"limit": 20,
"offset": 0
}

Response Fields​

FieldTypeDescription
idStringRelationship identifier
follower_idStringAccount doing the following
followerAccountFollower account details
following_idStringAccount being followed
followingAccountFollowed account details
created_atDateTimeWhen the follow was created

Expected Response​

{
"data": {
"following": [
{
"id": "0x123...",
"follower_id": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"follower": {
"label": "vitalik.eth",
"image": "ipfs://Qm..."
},
"following_id": "0xabc...",
"following": {
"label": "alice.eth",
"image": "ipfs://Qm..."
},
"created_at": "2024-01-15T10:30:00Z"
}
],
"following_aggregate": {
"aggregate": {
"count": 150
}
}
}
}

Interactive Example​

Query

query GetFollowing($account_id: String!, $limit: Int!) {
  following(
    where: { follower_id: { _eq: $account_id } }
    limit: $limit
    order_by: { created_at: desc }
  ) {
    following {
      id
      label
      image
    }
    created_at
  }
  following_aggregate(where: { follower_id: { _eq: $account_id } }) {
    aggregate {
      count
    }
  }
}

Variables

Click "Run Query" to execute the GraphQL query and see results

Use Cases​

Following List​

Get list of accounts a user follows:

async function getFollowing(accountId: string, options: {
limit?: number
offset?: number
} = {}) {
const query = `
query GetFollowing($account_id: String!, $limit: Int!, $offset: Int!) {
following(
where: { follower_id: { _eq: $account_id } }
order_by: { created_at: desc }
limit: $limit
offset: $offset
) {
following {
id
label
image
}
created_at
}
following_aggregate(where: { follower_id: { _eq: $account_id } }) {
aggregate {
count
}
}
}
`

const data = await client.request(query, {
account_id: accountId,
limit: options.limit || 20,
offset: options.offset || 0
})

return {
accounts: data.following.map(f => f.following),
total: data.following_aggregate.aggregate.count
}
}

Followers List​

Get accounts that follow a user:

async function getFollowers(accountId: string) {
const query = `
query GetFollowers($account_id: String!) {
following(
where: { following_id: { _eq: $account_id } }
order_by: { created_at: desc }
) {
follower {
id
label
image
}
created_at
}
following_aggregate(where: { following_id: { _eq: $account_id } }) {
aggregate {
count
}
}
}
`

const data = await client.request(query, { account_id: accountId })

return {
followers: data.following.map(f => f.follower),
count: data.following_aggregate.aggregate.count
}
}

Check if Following​

Check if one account follows another:

async function isFollowing(
followerId: string,
followingId: string
): Promise<boolean> {
const query = `
query CheckFollowing($follower: String!, $following: String!) {
following(where: {
follower_id: { _eq: $follower }
following_id: { _eq: $following }
}) {
id
}
}
`

const data = await client.request(query, {
follower: followerId,
following: followingId
})

return data.following.length > 0
}

React Following Component​

function FollowingList({ accountId }: { accountId: string }) {
const [tab, setTab] = useState<'following' | 'followers'>('following')

const { data, loading } = useQuery(
tab === 'following' ? GET_FOLLOWING : GET_FOLLOWERS,
{ variables: { account_id: accountId } }
)

const accounts = data?.following?.map(f =>
tab === 'following' ? f.following : f.follower
) || []

const count = data?.following_aggregate?.aggregate?.count || 0

return (
<div>
<div className="tabs">
<button
onClick={() => setTab('following')}
className={tab === 'following' ? 'active' : ''}
>
Following
</button>
<button
onClick={() => setTab('followers')}
className={tab === 'followers' ? 'active' : ''}
>
Followers
</button>
</div>

<p>{count} {tab}</p>

{loading ? (
<Spinner />
) : (
<ul>
{accounts.map(account => (
<li key={account.id}>
<AccountCard account={account} />
</li>
))}
</ul>
)}
</div>
)
}

How Following Works​

Following relationships are created through:

  1. Creating "Follow" triples (subject follows object)
  2. The indexer extracts these into the following table

Best Practices​

  1. Paginate lists - Following lists can be large
  2. Cache counts - Aggregate counts are relatively stable
  3. Show mutual follows - Indicate when users follow each other
  4. Use for feeds - Power social features with following data