// Feed with no extra fields, of feed group "user"
let feed = client.feed(group: "user", id: "john")
try await feed.getOrCreate()
// More options
let query = FeedQuery(
group: "user",
id: "jack",
data: .init(
description: "My personal feed",
name: "jack",
visibility: "public"
)
)
let feed2 = client.feed(for: query)
try await feed.getOrCreate()
Feeds
Creating a Feed
// Feed with no extra fields, of feed group "user"
val feed = client.feed(group = "user", id = "john")
feed.getOrCreate()
// More options
val query = FeedQuery(
group = "user",
id = "jack",
data = FeedInputData(
description = "My personal feed",
name = "jack",
visibility = FeedVisibility.Public
)
)
val feed2 = client.feed(query = query)
feed2.getOrCreate()
// Feed with no extra fields, of feed group "user"
const feed = client.feed("user", "jack");
await feed.getOrCreate();
// Subscribe to WebSocket events for state updates
await feed.getOrCreate({ watch: true });
// More options
const feed = client.feed("user", "jack");
await feed.getOrCreate({
data: {
description: "My personal feed",
name: "jack",
visibility: "public",
},
});
// Feed with no extra fields, of feed group "user"
final feed = client.feed(group: 'user', id: 'john');
await feed.getOrCreate();
// More options
const query = FeedQuery(
fid: FeedId(group: 'user', id: 'jack'),
data: FeedInputData(
description: 'My personal feed',
name: 'jack',
visibility: FeedVisibility.public,
),
);
final feed2 = client.feedFromQuery(query);
await feed2.getOrCreate();
// Feed with no extra fields, of feed group "user"
const feed = client.feeds.feed("user", "jack");
await feed.getOrCreate({
// The owner of the feed
user_id: "<user id>",
});
// More options
const feed = client.feeds.feed("user", "jack");
await feed.getOrCreate({
data: {
description: "My personal feed",
name: "jack",
visibility: "public",
},
// The owner of the feed
user_id: "<user id>",
});
// Example 1
response, err := feed.GetOrCreate(context.Background(), &getstream.GetOrCreateFeedRequest{
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error:", err)
}
log.Printf("Success: %+v\n", response)
// Example 2
response2, err := feed.GetOrCreate(context.Background(), &getstream.GetOrCreateFeedRequest{
UserID: getstream.PtrTo("john"),
Data: &getstream.FeedInput{
Description: getstream.PtrTo("My personal feed"),
Name: getstream.PtrTo("John Hikes"),
Visibility: getstream.PtrTo("public"),
}})
if err != nil {
log.Fatal("Error creating advanced feed:", err)
}
log.Printf("Success: %+v\n", response2)
testFeed = new Feed("user", testUserId, feeds);
testFeed2 = new Feed("user", testUserId2, feeds);
GetOrCreateFeedRequest feedRequest1 =
GetOrCreateFeedRequest.builder().userID(testUserId).build();
GetOrCreateFeedRequest feedRequest2 =
GetOrCreateFeedRequest.builder().userID(testUserId2).build();
GetOrCreateFeedResponse feedResponse1 = testFeed.getOrCreate(feedRequest1).getData();
GetOrCreateFeedResponse feedResponse2 = testFeed2.getOrCreate(feedRequest2).getData();
testFeedId = feedResponse1.getFeed().getFeed();
testFeedId2 = feedResponse2.getFeed().getFeed();
$feed = $feedsClient->feed('user', 'john');
$feedResponse = $feed->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(userID: 'john')
);
// More options
$feed2 = $feedsClient->feed('user', 'jack');
$feedResponse2 = $feed2->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(
userID: 'jack',
data: new GeneratedModels\FeedInput(
description: 'My personal feed',
name: 'jack',
visibility: 'public'
)
)
);
var feedResponse1 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId,
request: new GetOrCreateFeedRequest { UserID = _testUserId }
);
var feedResponse2 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId2,
request: new GetOrCreateFeedRequest { UserID = _testUserId2 }
);
feed_response_1 = self.test_feed.get_or_create(user_id=self.test_user_id)
feed_response_2 = self.test_feed_2.get_or_create(
user_id=self.test_user_id_2
)
require 'getstream_ruby'
# Feed with no extra fields, of feed group "user"
feed = client.feed('user', 'john')
request = GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
feed_response = feed.get_or_create_feed(request)
# More options with custom data
feed2 = client.feed('user', 'jack')
request2 = GetStream::Generated::Models::GetOrCreateFeedRequest.new(
user_id: 'jack',
data: GetStream::Generated::Models::FeedInput.new(
description: 'My personal feed',
name: 'jack',
visibility: 'public'
)
)
feed_response2 = feed2.get_or_create_feed(request2)
Built-in feed groups
Group | Description |
---|---|
user | A feed setup for the content a user creates. Typically you add activities here when someone writes a post |
timeline | The timeline feed is used when you’re following. So if user Charlie is following John, timeline:charlie would follow user:john |
foryou | A version of the timeline feed that adds popular content, and priorities popularity over recency |
notification | A notification feed. Think of the bell icon you see in most apps |
story | A feed set up for users to post story activities (activities with expiration data) |
stories | A timeline feed which can be used to follow other users’ stories. |
Reading a Feed
Here is a basic example of how to read a feed:
let feed = client.feed(group: "user", id: "john")
try await feed.getOrCreate()
let feedData = feed.state.feed
let activities = feed.state.activities
let members = feed.state.members
val feed = client.feed(group = "user", id = "john")
feed.getOrCreate()
val feedData = feed.state.feed
val activities = feed.state.activities
val members = feed.state.members
const feed = client.feed("user", "john");
await feed.getOrCreate({ watch: true });
const currentState = feed.state.getLatestValue();
const visivility = currentState.visibility;
const name = currentState.name;
const description = currentState.description;
const activities = currentState.activities;
const members = currentState.members;
// Or subscribe to state changes
const unsubscribe = feed.state.subscribe((state) => {
// Called everytime the state changes
console.log(state);
});
// or if you care only part of the state
const unsubscribe2 = feed.state.subscribeWithSelector(
(state) => ({
activities: state.activities,
}),
(state, prevState) => {
console.log(state.activities, prevState?.activities);
},
);
// Unsubscribe when you no longer want to recieve updates
unsubscribe();
unsubscribe2();
final feed = client.feed(group: 'user', id: 'john');
await feed.getOrCreate();
final feedData = feed.state.feed;
final activities = feed.state.activities;
final members = feed.state.members;
// Note: Always dispose the feed when you are done with it
feed.dispose();
const feed = client.feed(group: "user", id: "john")
const response = await feed.getOrCreate({
user_id: '<user id>'
})
const feedData = response.feed;
const activities = response.activities;
const members = response.members;
feed := client.Feeds().Feed("user", "john")
response, err := feed.GetOrCreate(context.Background(), &getstream.GetOrCreateFeedRequest{
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error calling getOrCreate:", err)
}
feedData := response.Data.Feed
activities := response.Data.Activities
members := response.Data.Members
testFeed = new Feed("user", testUserId, feeds);
GetOrCreateFeedRequest feedRequest1 =
GetOrCreateFeedRequest.builder().userID(testUserId).build();
GetOrCreateFeedResponse feedResponse1 = testFeed.getOrCreate(feedRequest1).getData();
testFeedId = feedResponse1.getFeed().getFeed();
$feed = $feedsClient->feed('user', 'john');
$response = $feed->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(userID: 'john')
);
// Access feed data
$feedData = $response->getData()->feed;
$activities = $response->getData()->activities;
$members = $response->getData()->members;
var feedResponse1 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId,
request: new GetOrCreateFeedRequest { UserID = _testUserId }
);
feed_response_1 = self.test_feed.get_or_create(user_id=self.test_user_id)
require 'getstream_ruby'
# Reading a feed
feed = client.feed('user', 'john')
request = GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
feed_response = feed.get_or_create_feed(request)
# Access feed data
feed_data = feed_response.feed
activities = feed_response.activities
members = feed_response.members
The response will contain the following data.
You have more options when reading a feed, let’s go over a few:
let query = FeedQuery(
group: "user",
id: "john",
activityFilter: .in(.filterTags, ["green"]), // filter activities with filter tag green
activityLimit: 10,
externalRanking: ["user_score": 0.8], // additional data used for ranking
followerLimit: 10,
followingLimit: 10,
memberLimit: 10,
view: "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
watch: true // receive web-socket events with real-time updates
)
let feed = client.feed(for: query)
try await feed.getOrCreate()
let activities = feed.state.activities
let feedData = feed.state.feed
val query = FeedQuery(
group = "user",
id = "john",
activityFilter = ActivitiesFilterField.filterTags.`in`("green"), // filter activities with filter tag green
activityLimit = 10,
externalRanking = mapOf("user_score" to 0.8), // additional data used for ranking
followerLimit = 10,
followingLimit = 10,
memberLimit = 10,
view = "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
watch = true // receive web-socket events with real-time updates
)
val feed = client.feed(query = query)
feed.getOrCreate()
val activities = feed.state.activities
val feedData = feed.state.feed
const feed = client.feed("user", "jack");
const response = await feed.getOrCreate({
limit: 10,
filter: {
filter_tags: ["green"], // filter activities with filter tag green
},
external_ranking: {
user_score: 0.8, // additional data used for ranking
},
followers_pagination: {
limit: 10,
},
following_pagination: {
limit: 10,
},
member_pagination: {
limit: 10,
},
view: "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
});
const query = FeedQuery(
fid: FeedId(group: 'user', id: 'john'),
// filter activities with filter tag green
activityFilter: Filter.in_(
ActivitiesFilterField.filterTags,
['green'],
),
activityLimit: 10,
// additional data used for ranking
externalRanking: {'user_score': 0.8},
followerLimit: 10,
followingLimit: 10,
memberLimit: 10,
// overwrite the default ranking or aggregation logic for this feed. good for split testing
view: 'myview',
// receive web-socket events with real-time updates
watch: true,
);
final feed = client.feedFromQuery(query);
await feed.getOrCreate();
final activities = feed.state.activities;
final feedData = feed.state.feed;
// Note: Always dispose the feed when you are done with it
feed.dispose();
const feed = client.feeds.feed("user", "jack");
const response = await feed.getOrCreate({
limit: 10,
filter: {
filter_tags: ["green"], // filter activities with filter tag green
},
external_ranking: {
user_score: 0.8, // additional data used for ranking
},
followers_pagination: {
limit: 10,
},
following_pagination: {
limit: 10,
},
member_pagination: {
limit: 10,
},
view: "myview", // overwrite the default ranking or aggregation logic for this feed. good for split testing
user_id: "<user id>",
});
feed := client.Feeds().Feed("user", "jack")
request := &getstream.GetOrCreateFeedRequest{
Limit: intPtr(10),
UserID: stringPtr("<user id>"),
View: stringPtr("myview"),
Filter: map[string]any{
"filter_tags": []string{"green"}, // filter activities with filter tag green
},
ExternalRanking: map[string]any{
"user_score": 0.8, // additional data used for ranking
},
FollowersPagination: &getstream.PagerRequest{
Limit: intPtr(10),
},
FollowingPagination: &getstream.PagerRequest{
Limit: intPtr(10),
},
MemberPagination: &getstream.PagerRequest{
Limit: intPtr(10),
},
}
response, err := feed.GetOrCreate(context.Background(), request)
testFeed = new Feed("user", testUserId, feeds);
testFeed2 = new Feed("user", testUserId2, feeds);
GetOrCreateFeedRequest feedRequest1 =
GetOrCreateFeedRequest.builder().userID(testUserId).build();
GetOrCreateFeedRequest feedRequest2 =
GetOrCreateFeedRequest.builder().userID(testUserId2).build();
GetOrCreateFeedResponse feedResponse1 = testFeed.getOrCreate(feedRequest1).getData();
GetOrCreateFeedResponse feedResponse2 = testFeed2.getOrCreate(feedRequest2).getData();
testFeedId = feedResponse1.getFeed().getFeed();
testFeedId2 = feedResponse2.getFeed().getFeed();
$feed = $feedsClient->feed('user', 'jack');
$response = $feed->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(
limit: 10,
filter: (object)['filter_tags' => ['green']],
externalRanking: (object)['user_score' => 0.8],
followersPagination: new GeneratedModels\PagerRequest(limit: 10),
followingPagination: new GeneratedModels\PagerRequest(limit: 10),
memberPagination: new GeneratedModels\PagerRequest(limit: 10),
view: 'myview',
userID: 'jack'
)
);
var feedResponse1 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId,
request: new GetOrCreateFeedRequest { UserID = _testUserId }
);
var feedResponse2 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId2,
request: new GetOrCreateFeedRequest { UserID = _testUserId2 }
);
feed_response_1 = self.test_feed.get_or_create(user_id=self.test_user_id)
feed_response_2 = self.test_feed_2.get_or_create(
user_id=self.test_user_id_2
)
require 'getstream_ruby'
# Reading multiple feeds
feed1 = client.feed('user', 'john')
request1 = GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'john')
feed_response_1 = feed1.get_or_create_feed(request1)
feed2 = client.feed('user', 'jane')
request2 = GetStream::Generated::Models::GetOrCreateFeedRequest.new(user_id: 'jane')
feed_response_2 = feed2.get_or_create_feed(request2)
Feed Pagination
Here is how you can read the next page on the feed:
let feed = client.feed(
for: .init(
group: "user",
id: "john",
activityLimit: 10
)
)
// Page 1
try await feed.getOrCreate()
let activities = feed.state.activities // First 10 activities
// Page 2
let page2Activities = try await feed.queryMoreActivities(limit: 10)
let page1And2Activities = feed.state.activities
val feed = client.feed(
query = FeedQuery(
group = "user",
id = "john",
activityLimit = 10
)
)
// Page 1
feed.getOrCreate()
val activities = feed.state.activities // First 10 activities
// Page 2
val page2Activities: Result<List<ActivityData>> = feed.queryMoreActivities(limit = 10)
val page1And2Activities = feed.state.activities
const feed = client.feed("user", "jack");
// First page
await feed.getOrCreate({
limit: 10,
});
// Second page
await feed.getNextPage();
console.log(feed.state.getLatestValue().activities);
// Only if feed group has aggregation turned on
console.log(feed.state.getLatestValue().aggregated_activities);
final feed = client.feedFromQuery(
const FeedQuery(
fid: FeedId(group: 'user', id: 'john'),
activityLimit: 10,
),
);
// Page 1
await feed.getOrCreate();
final activities = feed.state.activities; // First 10 activities
// Page 2
final page2Activities = await feed.queryMoreActivities(limit: 10);
final page1And2Activities = feed.state.activities;
const feed = client.feeds.feed("user", "jack");
const firstPage = await feed.getOrCreate({
limit: 10,
user_id: "user_id",
});
const nextPage = await feed.getOrCreate({
next: firstPage.next,
limit: 10,
user_id: "user_id",
});
feed := client.Feeds().Feed("user", "john")
// First page
firstPage, err := feed.GetOrCreate(context.Background(), &getstream.GetOrCreateFeedRequest{
Limit: getstream.PtrTo(10),
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error getting first page:", err)
}
// Second page request using next cursor
nextPage, err := feed.GetOrCreate(context.Background(), &getstream.GetOrCreateFeedRequest{
Next: firstPage.Data.Next,
Limit: getstream.PtrTo(10),
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error getting next page:", err)
}
log.Printf("First page activities count: %d", len(firstPage.Data.Activities))
log.Printf("Next page activities count: %d", len(nextPage.Data.Activities))
testFeed = new Feed("user", testUserId, feeds);
testFeed2 = new Feed("user", testUserId2, feeds);
GetOrCreateFeedRequest feedRequest1 =
GetOrCreateFeedRequest.builder().userID(testUserId).build();
GetOrCreateFeedRequest feedRequest2 =
GetOrCreateFeedRequest.builder().userID(testUserId2).build();
GetOrCreateFeedResponse feedResponse1 = testFeed.getOrCreate(feedRequest1).getData();
GetOrCreateFeedResponse feedResponse2 = testFeed2.getOrCreate(feedRequest2).getData();
testFeedId = feedResponse1.getFeed().getFeed();
testFeedId2 = feedResponse2.getFeed().getFeed();
$feed = $feedsClient->feed('user', 'jack');
$feedResponse1 = $feed->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(userID: "jack", limit: 10)
);
$feedResponse2 = $feed->getOrCreateFeed(
new GeneratedModels\GetOrCreateFeedRequest(userID: "jack", limit: 10, next: $feedResponse1->getData()->next)
);
var feedResponse1 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId,
request: new GetOrCreateFeedRequest { UserID = _testUserId }
);
var feedResponse2 = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: _testFeedId2,
request: new GetOrCreateFeedRequest { UserID = _testUserId2 }
);
feed_response_1 = self.test_feed.get_or_create(user_id=self.test_user_id)
feed_response_2 = self.test_feed_2.get_or_create(
user_id=self.test_user_id_2
)
Filtering Examples
Another common use case is filtering a feed. This is trickier than it seems. Keep in mind that for performance reasons feeds often have to be computed on write time. To allow for filtering we expose the following API.
// Add a few activities
let feedId = FeedId(group: "user", id: "john")
try await client.upsertActivities([
ActivityRequest(feeds: [feedId.rawValue], filterTags: ["green", "blue"], text: "first", type: "post"),
ActivityRequest(feeds: [feedId.rawValue], filterTags: ["yellow", "blue"], text: "second", type: "post"),
ActivityRequest(feeds: [feedId.rawValue], filterTags: ["orange"], text: "third", type: "post")
])
// Now read the feed, this will fetch activity 1 and 2
let query = FeedQuery(feed: feedId, activityFilter: .in(.filterTags, ["blue"]))
let feed = client.feed(for: query)
try await feed.getOrCreate()
let activities = feed.state.activities // contains first and second
// Add a few activities
val fid = FeedId(group = "user", id = "john")
client.upsertActivities(
listOf(
ActivityRequest(feeds = listOf(fid.rawValue), filterTags = listOf("green", "blue"), text = "first", type = "post"),
ActivityRequest(feeds = listOf(fid.rawValue), filterTags = listOf("yellow", "blue"), text = "second", type = "post"),
ActivityRequest(feeds = listOf(fid.rawValue), filterTags = listOf("orange"), text = "third", type = "post")
)
)
// Now read the feed, this will fetch activity 1 and 2
val query = FeedQuery(fid = fid, activityFilter = ActivitiesFilterField.filterTags.`in`("blue"))
val feed = client.feed(query = query)
feed.getOrCreate()
val activities = feed.state.activities // contains first and second
const feed = client.feed("user", "123");
// Add a few activities
client.upsertActivities({
activities: [
{
feeds: [feed.feed],
type: "post",
text: "first",
filter_tags: ["green", "blue"],
},
{
feeds: [feed.feed],
type: "post",
text: "second",
filter_tags: ["yellow", "blue"],
},
{
feeds: [feed.feed],
type: "post",
text: "third",
filter_tags: ["orange"],
},
],
});
const response = await feed.getOrCreate({
filter: {
filter_tags: ["blue"],
},
});
// Add a few activities
const feedId = FeedId(group: 'user', id: 'john');
await client.upsertActivities(
activities: [
ActivityRequest(
feeds: [feedId.rawValue],
filterTags: const ['green', 'blue'],
text: 'first',
type: 'post',
),
ActivityRequest(
feeds: [feedId.rawValue],
filterTags: const ['yellow', 'blue'],
text: 'second',
type: 'post',
),
ActivityRequest(
feeds: [feedId.rawValue],
filterTags: const ['orange'],
text: 'third',
type: 'post',
),
],
);
// Now read the feed, this will fetch activity 1 and 2
const query = FeedQuery(
fid: feedId,
activityFilter: Filter.in_(ActivitiesFilterField.filterTags, ['blue']),
);
final feed = client.feedFromQuery(query);
await feed.getOrCreate();
// contains first and second
final activities = feed.state.activities;
const feed = client.feeds.feed("user", "123");
// Add a few activities
client.feeds.upsertActivities({
activities: [
{
feeds: [feed.feed],
type: "post",
text: "first",
filter_tags: ["green", "blue"],
user_id: "<user id>",
},
{
feeds: [feed.feed],
type: "post",
text: "second",
filter_tags: ["yellow", "blue"],
user_id: "<user id>",
},
{
feeds: [feed.feed],
type: "post",
text: "third",
filter_tags: ["orange"],
user_id: "<user id>",
},
],
});
const response = await feed.getOrCreate({
filter: {
filter_tags: ["blue"],
},
user_id: "<user id>",
});
ctx := context.Background()
// Create feed
feed := client.Feeds().Feed("user", "john")
// Create activities
activities := []getstream.ActivityRequest{
{
Feeds: []string{"user:john"},
Type: "post",
Text: stringPtr("first"),
FilterTags: []string{"green", "blue"},
UserID: stringPtr("john"),
},
{
Feeds: []string{"user:john"},
Type: "post",
Text: stringPtr("second"),
FilterTags: []string{"yellow", "blue"},
UserID: stringPtr("john"),
},
{
Feeds: []string{"user:john"},
Type: "post",
Text: stringPtr("third"),
FilterTags: []string{"orange"},
UserID: stringPtr("john"),
},
}
// Upsert activities
_, err = client.Feeds().UpsertActivities(ctx, &getstream.UpsertActivitiesRequest{
Activities: activities,
})
if err != nil {
log.Fatal("Error upserting activities:", err)
}
// Get or create feed with filter
response, err := feed.GetOrCreate(ctx, &getstream.GetOrCreateFeedRequest{
Filter: map[string]any{
"filter_tags": []string{"blue"},
},
UserID: stringPtr("john"),
})
if err != nil {
log.Fatal("Error getting or creating feed:", err)
}
log.Printf("Feed response: %+v", len(response.Data.Activities))
// Add a few activities
List<ActivityRequest> activities = List.of(
ActivityRequest.builder()
.feeds(List.of("user:123"))
.type("post")
.text("first")
.filterTags(List.of("green", "blue"))
.userID("123")
.build(),
ActivityRequest.builder()
.feeds(List.of("user:123"))
.type("post")
.text("second")
.filterTags(List.of("yellow", "blue"))
.userID("123")
.build(),
ActivityRequest.builder()
.feeds(List.of("user:123"))
.type("post")
.text("third")
.filterTags(List.of("orange"))
.userID("123")
.build()
);
feeds.upsertActivities(
UpsertActivitiesRequest.builder()
.activities(activities)
.build()
).execute();
// Now read the feed, this will fetch activity 1 and 2
Map<String, Object> filter = new HashMap<>();
filter.put("filter_tags", List.of("blue"));
GetOrCreateFeedRequest feedRequest = GetOrCreateFeedRequest.builder()
.filter(filter)
.userID("123")
.build();
GetOrCreateFeedResponse response = feeds.getOrCreateFeed("user", "123", feedRequest).execute().getData();
$feed = $feedsClient->feed('user', '123');
// Add a few activities
$feedsClient->upsertActivities(
new GeneratedModels\UpsertActivitiesRequest(
activities: [
[
'feeds' => [$feed->getFeedIdentifier()],
'type' => 'post',
'text' => 'first',
'filter_tags' => ['green', 'blue'],
'user_id' => '123',
],
[
'feeds' => [$feed->getFeedIdentifier()],
'type' => 'post',
'text' => 'second',
'filter_tags' => ['yellow', 'blue'],
'user_id' => '123',
],
[
'feeds' => [$feed->getFeedIdentifier()],
'type' => 'post',
'text' => 'third',
'filter_tags' => ['orange'],
'user_id' => '123',
],
]
)
);
// Now read the feed, this will fetch activity 1 and 2
$response = $feedsClient->getOrCreateFeed(
'user',
'123',
new GeneratedModels\GetOrCreateFeedRequest(
filter: (object)['filter_tags' => ['blue']],
userID: '123'
)
);
// Add a few activities
await _feedsV3Client.UpsertActivitiesAsync(
request: new UpsertActivitiesRequest
{
Activities = new List<ActivityRequest>
{
new ActivityRequest
{
Feeds = new List<string> { "user:123" },
Type = "post",
Text = "first",
FilterTags = new List<string> { "green", "blue" },
UserID = "123"
},
new ActivityRequest
{
Feeds = new List<string> { "user:123" },
Type = "post",
Text = "second",
FilterTags = new List<string> { "yellow", "blue" },
UserID = "123"
},
new ActivityRequest
{
Feeds = new List<string> { "user:123" },
Type = "post",
Text = "third",
FilterTags = new List<string> { "orange" },
UserID = "123"
}
}
}
);
// Now read the feed, this will fetch activity 1 and 2
var response = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: "123",
request: new GetOrCreateFeedRequest
{
Filter = new { filter_tags = new[] { "blue" } },
UserID = "123"
}
);
# Add a few activities
feeds.upsert_activities(
activities=[
{
"feeds": ["user:123"],
"type": "post",
"text": "first",
"filter_tags": ["green", "blue"],
"user_id": "123"
},
{
"feeds": ["user:123"],
"type": "post",
"text": "second",
"filter_tags": ["yellow", "blue"],
"user_id": "123"
},
{
"feeds": ["user:123"],
"type": "post",
"text": "third",
"filter_tags": ["orange"],
"user_id": "123"
}
]
)
# Now read the feed, this will fetch activity 1 and 2
response = feeds.get_or_create_feed(
feed_group="user",
feed_id="123",
filter={"filter_tags": ["blue"]},
user_id="123"
)
# Add a few activities
client.feeds.upsert_activities(
GetStream::Generated::Models::UpsertActivitiesRequest.new(
activities: [
{
"feeds" => ["user:123"],
"type" => "post",
"text" => "first",
"filter_tags" => ["green", "blue"],
"user_id" => "123"
},
{
"feeds" => ["user:123"],
"type" => "post",
"text" => "second",
"filter_tags" => ["yellow", "blue"],
"user_id" => "123"
},
{
"feeds" => ["user:123"],
"type" => "post",
"text" => "third",
"filter_tags" => ["orange"],
"user_id" => "123"
}
]
)
)
# Now read the feed, this will fetch activity 1 and 2
response = client.feeds.get_or_create_feed(
"user",
"123",
GetStream::Generated::Models::GetOrCreateFeedRequest.new(
filter: { "filter_tags" => ["blue"] },
user_id: "123"
)
)
The filter syntax also supports $or
and $and
, so here’s an example that’s a little more complicated:
// Get all the activities where filter tags contain both "green" and "orange"
let query = FeedQuery(
group: "user",
id: "john",
activityFilter: .and([
.in(.filterTags, ["green"]),
.in(.filterTags, ["orange"])
])
)
try await feed.getOrCreate()
let activities = feed.state.activities
// Get all the activities where filter tags contain both "green" and "orange"
val query = FeedQuery(
group = "user",
id = "john",
activityFilter = Filters.and(
ActivitiesFilterField.filterTags.`in`("green"),
ActivitiesFilterField.filterTags.`in`("orange"),
)
)
feed.getOrCreate()
val activities = feed.state.activities
// Get all the activities where filter tags contain both "green" and "orange"
const response = await feed.getOrCreate({
filter: {
$and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
},
});
// Get all the activities where filter tags contain both "green" and "orange"
const query = FeedQuery(
fid: FeedId(group: 'user', id: 'john'),
activityFilter: Filter.and([
Filter.in_(ActivitiesFilterField.filterTags, ['green']),
Filter.in_(ActivitiesFilterField.filterTags, ['orange']),
]),
);
final feed = client.feedFromQuery(query);
await feed.getOrCreate();
final activities = feed.state.activities;
// Get all the activities where filter tags contain both "green" and "orange"
const response = await feed.getOrCreate({
filter: {
$and: [
{ filter_tags: ["green"] }
{ filter_tags: ["orange"] }
],
},
user_id: "<user id>",
});
// Get all the activities where filter tags contain both "green" and "orange"
feed := client.Feeds().Feed("user", "john")
response, err := feed.GetOrCreate(ctx, &getstream.GetOrCreateFeedRequest{
Filter: map[string]any{
"$and": []map[string]any{
{"filter_tags": []string{"green"}},
{"filter_tags": []string{"orange"}},
},
},
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error getting feed with filter:", err)
}
log.Printf("Activities: %+v", response.Data.Activities)
// Get all the activities where filter tags contain both "green" and "orange"
Map<String, Object> filter = new HashMap<>();
List<Map<String, Object>> andConditions = List.of(
Map.of("filter_tags", List.of("green")),
Map.of("filter_tags", List.of("orange"))
);
filter.put("$and", andConditions);
GetOrCreateFeedRequest request = GetOrCreateFeedRequest.builder()
.filter(filter)
.userID("john")
.build();
GetOrCreateFeedResponse response = feeds.getOrCreateFeed("user", "john", request).execute().getData();
$response = $feedsClient->getOrCreateFeed(
'user',
'123',
new GeneratedModels\GetOrCreateFeedRequest(
filter: (object)['and' => [
'filter_tags' => ['green'],
'filter_tags' => ['orange'],
]],
userID: '123'
)
);
// Get all the activities where filter tags contain both "green" and "orange"
var response = await _feedsV3Client.GetOrCreateFeedAsync(
FeedGroupID: "user",
FeedID: "john",
request: new GetOrCreateFeedRequest
{
Filter = new
{
and = new[]
{
new { filter_tags = new[] { "green" } },
new { filter_tags = new[] { "orange" } }
}
},
UserID = "john"
}
);
# Get all the activities where filter tags contain both "green" and "orange"
response = feeds.get_or_create_feed(
feed_group="user",
feed_id="john",
filter={
"$and": [
{"filter_tags": ["green"]},
{"filter_tags": ["orange"]}
]
},
user_id="john"
)
# Get all the activities where filter tags contain both "green" and "orange"
response = client.feeds.get_or_create_feed(
"user",
"john",
GetStream::Generated::Models::GetOrCreateFeedRequest.new(
filter: {
"$and" => [
{ "filter_tags" => ["green"] },
{ "filter_tags" => ["orange"] }
]
},
user_id: "john"
)
)
Feed Members
You can add and remove members to a feed. This is useful for building communities where a set of users can add content to the feed.
It’s not possible to set/update member role on client-side. Use server-side SDKs for this. When adding members client-side all new members will have feed_member
role:
// The following methods are available to edit the members of a feed
try await feed.updateFeedMembers(
request: .init(
members: [.init(
custom: ["joined": "2024-01-01"],
role: "moderator",
userId: "john"
)],
operation: .upsert
)
)
// Remove members
try await feed.updateFeedMembers(
request: .init(
members: [.init(userId: "john"), .init(userId: "jane")],
operation: .remove
)
)
// Set members (overwrites the list)
try await feed.updateFeedMembers(
request: .init(
members: [.init(role: "moderator", userId: "john")],
operation: .set
)
)
// The following methods are available to edit the members of a feed
feed.updateFeedMembers(
request = UpdateFeedMembersRequest(
members = listOf(
FeedMemberRequest(
custom = mapOf("joined" to "2024-01-01"),
role = "moderator",
userId = "john"
)
),
operation = UpdateFeedMembersRequest.Operation.Upsert
)
)
// Remove members
feed.updateFeedMembers(
request = UpdateFeedMembersRequest(
members = listOf(
FeedMemberRequest(userId = "john"),
FeedMemberRequest(userId = "jane")
),
operation = UpdateFeedMembersRequest.Operation.Remove
)
)
// Set members (overwrites the list)
feed.updateFeedMembers(
request = UpdateFeedMembersRequest(
members = listOf(
FeedMemberRequest(role = "moderator", userId = "john")
),
operation = UpdateFeedMembersRequest.Operation.Set
)
)
// The following methods are available to add or edit the members of a feed
await feed.updateFeedMembers({
operation: "upsert",
members: [
{
user_id: "john",
custom: {
joined: "2024-01-01",
},
},
],
});
// Remove members
await feed.updateFeedMembers({
operation: "remove",
members: [
{
user_id: "john",
},
{
user_id: "jane",
},
],
});
// Set members (overwrites the list)
await feed.updateFeedMembers({
operation: "set",
members: [
{
user_id: "john",
},
],
});
// The following methods are available to edit the members of a feed
final result = await feed.updateFeedMembers(
request: const UpdateFeedMembersRequest(
members: [
FeedMemberRequest(
custom: {'joined': '2024-01-01'},
role: 'moderator',
userId: 'john',
),
],
operation: UpdateFeedMembersRequestOperation.upsert,
),
);
// Remove members
await feed.updateFeedMembers(
request: const UpdateFeedMembersRequest(
members: [
FeedMemberRequest(userId: 'john'),
FeedMemberRequest(userId: 'jane'),
],
operation: UpdateFeedMembersRequestOperation.remove,
),
);
// Set members (overwrites the list)
await feed.updateFeedMembers(
request: const UpdateFeedMembersRequest(
members: [FeedMemberRequest(role: 'moderator', userId: 'john')],
operation: UpdateFeedMembersRequestOperation.set,
),
);
// The following methods are available to add or edit the members of a feed
await feed.updateFeedMembers({
operation: "upsert",
members: [
{
user_id: "john",
role: "moderator",
custom: {
joined: "2024-01-01",
},
},
],
});
// Remove members
await feed.updateFeedMembers({
operation: "remove",
members: [
{
user_id: "john",
},
{
user_id: "jane",
},
],
});
// Set members (overwrites the list)
await feed.updateFeedMembers({
operation: "set",
members: [
{
user_id: "john",
role: "moderator",
},
],
});
_, err = feed.UpdateFeedMembers(context.Background(), &getstream.UpdateFeedMembersRequest{
Operation: "upsert",
Members: []getstream.FeedMemberRequest{
{
UserID: "john",
Role: getstream.PtrTo("moderator"),
Custom: map[string]any{
"joined": "2024-01-01",
},
},
},
})
if err != nil {
log.Fatal(err)
}
// Remove members
_, err = feed.UpdateFeedMembers(context.Background(), &getstream.UpdateFeedMembersRequest{
Operation: "remove",
Members: []getstream.FeedMemberRequest{
{
UserID: "john",
},
{
UserID: "jane",
},
},
})
if err != nil {
log.Fatal(err)
}
// Set members (overwrites the list)
_, err = feed.UpdateFeedMembers(context.Background(), &getstream.UpdateFeedMembersRequest{
Operation: "set",
Members: []getstream.FeedMemberRequest{
{
UserID: "john",
Role: getstream.PtrTo("moderator"),
},
},
})
if err != nil {
log.Fatal(err)
}
// The following methods are available to edit the members of a feed
UpdateFeedMembersRequest upsertRequest = UpdateFeedMembersRequest.builder()
.operation("upsert")
.members(List.of(
FeedMemberRequest.builder()
.userID("john")
.role("moderator")
.custom(Map.of("joined", "2024-01-01"))
.build()
))
.build();
feeds.updateFeedMembers("user", "community_id", upsertRequest).execute();
// Remove members
UpdateFeedMembersRequest removeRequest = UpdateFeedMembersRequest.builder()
.operation("remove")
.members(List.of(
FeedMemberRequest.builder().userID("john").build(),
FeedMemberRequest.builder().userID("jane").build()
))
.build();
feeds.updateFeedMembers("user", "community_id", removeRequest).execute();
// Set members (overwrites the list)
UpdateFeedMembersRequest setRequest = UpdateFeedMembersRequest.builder()
.operation("set")
.members(List.of(
FeedMemberRequest.builder()
.userID("john")
.role("moderator")
.build()
))
.build();
feeds.updateFeedMembers("user", "community_id", setRequest).execute();
$feed = $feedsClient->feed('user', 'community_id');
// The following methods are available to edit the members of a feed
$feed->updateFeedMembers(
new GeneratedModels\UpdateFeedMembersRequest(
operation: 'upsert',
members: [
new GeneratedModels\FeedMemberRequest(
userID: 'john',
role: 'moderator',
custom: (object)['joined' => '2024-01-01']
),
]
)
);
// Remove members
$feed->updateFeedMembers(
new GeneratedModels\UpdateFeedMembersRequest(
operation: 'remove',
members: [
new GeneratedModels\FeedMemberRequest(userID: 'john'),
new GeneratedModels\FeedMemberRequest(userID: 'jane'),
]
)
);
// Set members (overwrites the list)
$feed->updateFeedMembers(
new GeneratedModels\UpdateFeedMembersRequest(
operation: 'set',
members: [
new GeneratedModels\FeedMemberRequest(
userID: 'john',
role: 'moderator'
),
]
)
);
// The following methods are available to edit the members of a feed
await _feedsV3Client.UpdateFeedMembersAsync(
FeedGroupID: "user",
FeedID: "community_id",
request: new UpdateFeedMembersRequest
{
Operation = "upsert",
Members = new List<FeedMemberRequest>
{
new FeedMemberRequest
{
UserID = "john",
Role = "moderator",
Custom = new { joined = "2024-01-01" }
}
}
}
);
// Remove members
await _feedsV3Client.UpdateFeedMembersAsync(
FeedGroupID: "user",
FeedID: "community_id",
request: new UpdateFeedMembersRequest
{
Operation = "remove",
Members = new List<FeedMemberRequest>
{
new FeedMemberRequest { UserID = "john" },
new FeedMemberRequest { UserID = "jane" }
}
}
);
// Set members (overwrites the list)
await _feedsV3Client.UpdateFeedMembersAsync(
FeedGroupID: "user",
FeedID: "community_id",
request: new UpdateFeedMembersRequest
{
Operation = "set",
Members = new List<FeedMemberRequest>
{
new FeedMemberRequest
{
UserID = "john",
Role = "moderator"
}
}
}
);
# The following methods are available to edit the members of a feed
feeds.update_feed_members(
feed_group="user",
feed_id="community_id",
operation="upsert",
members=[
{
"user_id": "john",
"role": "moderator",
"custom": {"joined": "2024-01-01"}
}
]
)
# Remove members
feeds.update_feed_members(
feed_group="user",
feed_id="community_id",
operation="remove",
members=[
{"user_id": "john"},
{"user_id": "jane"}
]
)
# Set members (overwrites the list)
feeds.update_feed_members(
feed_group="user",
feed_id="community_id",
operation="set",
members=[
{
"user_id": "john",
"role": "moderator"
}
]
)
# The following methods are available to edit the members of a feed
client.feeds.update_feed_members(
"user",
"community_id",
GetStream::Generated::Models::UpdateFeedMembersRequest.new(
operation: "upsert",
members: [
GetStream::Generated::Models::FeedMemberRequest.new(
user_id: "john",
role: "moderator",
custom: { "joined" => "2024-01-01" }
)
]
)
)
# Remove members
client.feeds.update_feed_members(
"user",
"community_id",
GetStream::Generated::Models::UpdateFeedMembersRequest.new(
operation: "remove",
members: [
GetStream::Generated::Models::FeedMemberRequest.new(user_id: "john"),
GetStream::Generated::Models::FeedMemberRequest.new(user_id: "jane")
]
)
)
# Set members (overwrites the list)
client.feeds.update_feed_members(
"user",
"community_id",
GetStream::Generated::Models::UpdateFeedMembersRequest.new(
operation: "set",
members: [
GetStream::Generated::Models::FeedMemberRequest.new(
user_id: "john",
role: "moderator"
)
]
)
)
Feed members vs followers
Followers and members might seem like similar concepts, but they serve two different purposes with some key differences.
Followers can only be feeds (for example the timeline
feed of Alice follows the user
feed of Bob). Followers’ aim is to access the content of a feed they’re interested in and interact with it.
Members can only be users (for example Alice adds Bob as a member to her feed about “Travel Hacks”). The aim of feed members is usually to help out with admin tasks (helpful if you want to build apps similar to Facebook pages) or to decide what activities a user has access to using membership levels (for example Bob becomes a premium member in Alice’s community).
Member invites
You can invite members with the invite
flag, where invited users can accept or reject the membership.
// Request to become a member
try await feed.updateFeedMembers(
request: .init(
members: [.init(
custom: ["reason": "community builder"],
invite: true,
role: "moderator",
userId: "john"
)],
operation: .upsert
)
)
// Accept and reject member requests
_ = try await feed.acceptFeedMember()
_ = try await feed.rejectFeedMember()
// Request to become a member
feed.updateFeedMembers(
request = UpdateFeedMembersRequest(
members = listOf(
FeedMemberRequest(
custom = mapOf("reason" to "community builder"),
invite = true,
role = "moderator",
userId = "john"
)
),
operation = UpdateFeedMembersRequest.Operation.Upsert
)
)
// Accept and reject member requests
feed.acceptFeedMember()
feed.rejectFeedMember()
await invitingFeed.updateFeedMembers({
operation: "upsert",
members: [
{
user_id: "john",
invite: true,
custom: {
reason: "community builder",
},
},
],
});
const feed = johnClient.feed(invitingFeed.group, invitingFeed.id);
// Then John can accept or reject
await feed.acceptFeedMemberInvite();
await feed.rejectFeedMemberInvite();
// Request to become a member
await feed.updateFeedMembers(
request: const UpdateFeedMembersRequest(
members: [
FeedMemberRequest(
custom: {'reason': 'community builder'},
invite: true,
role: 'moderator',
userId: 'john',
),
],
operation: UpdateFeedMembersRequestOperation.upsert,
),
);
// Accept and reject member requests
await feed.acceptFeedMember();
await feed.rejectFeedMember();
await feed.updateFeedMembers({
operation: "upsert",
members: [
{
user_id: "john",
role: "moderator",
invite: true,
custom: {
reason: "community builder",
},
},
],
});
await feed.acceptFeedMemberInvite({
user_id: "john",
});
await feed.rejectFeedMemberInvite({
user_id: "john",
});
// Create feed
feed := client.Feeds().Feed("user", "alice")
// Update feed members with upsert operation
updateResponse, err := feed.UpdateFeedMembers(context.Background(), &getstream.UpdateFeedMembersRequest{
Operation: "upsert",
Members: []getstream.FeedMemberRequest{
{
UserID: "john",
Role: getstream.PtrTo("moderator"),
Invite: getstream.PtrTo(true),
Custom: map[string]any{
"reason": "community builder",
},
},
},
})
if err != nil {
log.Fatal("Error updating feed members:", err)
}
log.Printf("Feed members updated: %+v", updateResponse)
// Accept feed member invite
acceptResponse, err := feed.AcceptFeedMemberInvite(context.Background(), &getstream.AcceptFeedMemberInviteRequest{
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error accepting feed member invite:", err)
}
log.Printf("Feed member invite accepted: %+v", acceptResponse)
// Reject feed member invite
rejectResponse, err := feed.RejectFeedMemberInvite(context.Background(), &getstream.RejectFeedMemberInviteRequest{
UserID: getstream.PtrTo("john"),
})
if err != nil {
log.Fatal("Error rejecting feed member invite:", err)
}
log.Printf("Feed member invite rejected: %+v", rejectResponse)
// Invite a member
UpdateFeedMembersRequest inviteRequest = UpdateFeedMembersRequest.builder()
.operation("upsert")
.members(List.of(
FeedMemberRequest.builder()
.userID("john")
.role("moderator")
.invite(true)
.custom(Map.of("reason", "community builder"))
.build()
))
.build();
feeds.updateFeedMembers("user", "alice", inviteRequest).execute();
// Accept feed member invite
AcceptFeedMemberInviteRequest acceptRequest = AcceptFeedMemberInviteRequest.builder()
.userID("john")
.build();
feeds.acceptFeedMemberInvite("user", "alice", acceptRequest).execute();
// Reject feed member invite
RejectFeedMemberInviteRequest rejectRequest = RejectFeedMemberInviteRequest.builder()
.userID("john")
.build();
feeds.rejectFeedMemberInvite("user", "alice", rejectRequest).execute();
$feed = $feedsClient->feed('user', 'alice');
// Invite a member
$feed->updateFeedMembers(
new GeneratedModels\UpdateFeedMembersRequest(
operation: 'upsert',
members: [
new GeneratedModels\FeedMemberRequest(
userID: 'john',
role: 'moderator',
invite: true,
custom: (object)['reason' => 'community builder']
),
]
)
);
// Accept feed member invite
$feed->acceptFeedMemberInvite(
new GeneratedModels\AcceptFeedMemberInviteRequest(
userID: 'john'
)
);
// Reject feed member invite
$feed->rejectFeedMemberInvite(
new GeneratedModels\RejectFeedMemberInviteRequest(
userID: 'john'
)
);
// Invite a member
await _feedsV3Client.UpdateFeedMembersAsync(
FeedGroupID: "user",
FeedID: "alice",
request: new UpdateFeedMembersRequest
{
Operation = "upsert",
Members = new List<FeedMemberRequest>
{
new FeedMemberRequest
{
UserID = "john",
Role = "moderator",
Invite = true,
Custom = new { reason = "community builder" }
}
}
}
);
// Accept feed member invite
await _feedsV3Client.AcceptFeedMemberInviteAsync(
FeedGroupID: "user",
FeedID: "alice",
request: new AcceptFeedMemberInviteRequest { UserID = "john" }
);
// Reject feed member invite
await _feedsV3Client.RejectFeedMemberInviteAsync(
FeedGroupID: "user",
FeedID: "alice",
request: new RejectFeedMemberInviteRequest { UserID = "john" }
);
# Invite a member
feeds.update_feed_members(
feed_group="user",
feed_id="alice",
operation="upsert",
members=[
{
"user_id": "john",
"role": "moderator",
"invite": True,
"custom": {"reason": "community builder"}
}
]
)
# Accept feed member invite
feeds.accept_feed_member_invite(
feed_group="user",
feed_id="alice",
user_id="john"
)
# Reject feed member invite
feeds.reject_feed_member_invite(
feed_group="user",
feed_id="alice",
user_id="john"
)
# Invite a member
client.feeds.update_feed_members(
"user",
"alice",
GetStream::Generated::Models::UpdateFeedMembersRequest.new(
operation: "upsert",
members: [
GetStream::Generated::Models::FeedMemberRequest.new(
user_id: "john",
role: "moderator",
invite: true,
custom: { "reason" => "community builder" }
)
]
)
)
# Accept feed member invite
client.feeds.accept_feed_member_invite(
"user",
"alice",
GetStream::Generated::Models::AcceptFeedMemberInviteRequest.new(user_id: "john")
)
# Reject feed member invite
client.feeds.reject_feed_member_invite(
"user",
"alice",
GetStream::Generated::Models::RejectFeedMemberInviteRequest.new(user_id: "john")
)
Query Feeds
Querying feeds allows you to do things like showing the list of communities you’ve joined.
Here’s an example of how to query feeds:
Querying My Feeds
let query = FeedsQuery(
filter: .equal(.createdById, "john"),
sort: [Sort(field: .createdAt, direction: .reverse)],
limit: 10,
watch: true
)
let feedList = client.feedList(for: query)
// Page 1
let page1 = try await feedList.get()
// Page 2
let page2 = try await feedList.queryMoreFeeds(limit: 10)
let page1And2 = feedList.state.feeds
val query = FeedsQuery(
filter = FeedsFilterField.createdById.equal("john"),
sort = listOf(FeedsSort(FeedsSortField.CreatedAt, SortDirection.REVERSE)),
limit = 10,
watch = true
)
val feedList = client.feedList(query = query)
// Page 1
val page1: Result<List<FeedData>> = feedList.get()
// Page 2
val page2: Result<List<FeedData>> = feedList.queryMoreFeeds(limit = 10)
val page1And2 = feedList.state.feeds
const firstPage = await client.queryFeeds({
filter: {
created_by_id: "john",
},
limit: 10,
sort: [{ field: "created_at", direction: -1 }],
});
const secondPage = await client.queryFeeds({
filter: {
created_by_id: "john",
},
limit: 10,
sort: [{ field: "created_at", direction: -1 }],
next: firstPage.next,
});
final query = FeedsQuery(
filter: const Filter.equal(FeedsFilterField.createdById, 'john'),
sort: [FeedsSort.desc(FeedsSortField.createdAt)],
limit: 10,
watch: true,
);
final feedList = client.feedList(query);
// Page 1
final page1 = await feedList.get();
// Page 2
final page2 = await feedList.queryMoreFeeds(limit: 10);
final page1And2 = feedList.state.feeds;
const firstPage = await client.feeds.queryFeeds({
filter: {
created_by_id: "john",
},
limit: 10,
sort: [{ field: "created_at", direction: -1 }],
});
const secondPage = await client.feeds.queryFeeds({
filter: {
created_by_id: "john",
},
limit: 10,
sort: [{ field: "created_at", direction: -1 }],
next: firstPage.next,
});
ctx := context.Background()
// First page query
firstPage, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: map[string]any{
"created_by_id": "john",
},
Limit: getstream.PtrTo(10),
Sort: []getstream.SortParamRequest{
{
Field: getstream.PtrTo("created_at"),
Direction: getstream.PtrTo(-1),
},
},
})
if err != nil {
log.Fatal("Error querying first page:", err)
}
// Second page query using next cursor from first page
secondPage, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: map[string]any{
"created_by_id": "john",
},
Limit: getstream.PtrTo(10),
Sort: []getstream.SortParamRequest{
{
Field: getstream.PtrTo("created_at"),
Direction: getstream.PtrTo(-1),
},
},
Next: firstPage.Data.Next,
})
if err != nil {
log.Fatal("Error querying second page:", err)
}
log.Printf("First page: %d feeds, next: %v", len(firstPage.Data.Feeds), firstPage.Data.Next)
log.Printf("Second page: %d feeds, next: %v", len(secondPage.Data.Feeds), secondPage.Data.Next)
// First page query
Map<String, Object> filter = new HashMap<>();
filter.put("created_by_id", "john");
QueryFeedsRequest firstPageRequest = QueryFeedsRequest.builder()
.filter(filter)
.limit(10)
.sort(List.of(
SortParamRequest.builder()
.field("created_at")
.direction(-1)
.build()
))
.build();
QueryFeedsResponse firstPage = feeds.queryFeeds(firstPageRequest).execute().getData();
// Second page using next cursor from first page
QueryFeedsRequest secondPageRequest = QueryFeedsRequest.builder()
.filter(filter)
.limit(10)
.sort(List.of(
SortParamRequest.builder()
.field("created_at")
.direction(-1)
.build()
))
.next(firstPage.getNext())
.build();
QueryFeedsResponse secondPage = feeds.queryFeeds(secondPageRequest).execute().getData();
// First page query
$firstPage = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)['created_by_id' => 'john'],
limit: 10,
sort: [
['field' => 'created_at', 'direction' => -1]
]
)
);
// Second page using next cursor from first page
$secondPage = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)['created_by_id' => 'john'],
limit: 10,
sort: [
['field' => 'created_at', 'direction' => -1]
],
next: $firstPage->getData()->next
)
);
// First page query
var firstPage = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new { created_by_id = "john" },
Limit = 10,
Sort = new List<SortParamRequest>
{
new SortParamRequest
{
Field = "created_at",
Direction = -1
}
}
}
);
// Second page using next cursor from first page
var secondPage = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new { created_by_id = "john" },
Limit = 10,
Sort = new List<SortParamRequest>
{
new SortParamRequest
{
Field = "created_at",
Direction = -1
}
},
Next = firstPage.Next
}
);
# First page query
first_page = feeds.query_feeds(
filter={"created_by_id": "john"},
limit=10,
sort=[{"field": "created_at", "direction": -1}]
)
# Second page using next cursor from first page
second_page = feeds.query_feeds(
filter={"created_by_id": "john"},
limit=10,
sort=[{"field": "created_at", "direction": -1}],
next=first_page["next"]
)
# First page query
first_page = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: { "created_by_id" => "john" },
limit: 10,
sort: [{ "field" => "created_at", "direction" => -1 }]
)
)
# Second page using next cursor from first page
second_page = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: { "created_by_id" => "john" },
limit: 10,
sort: [{ "field" => "created_at", "direction" => -1 }],
_next: first_page.data._next
)
)
Querying Feeds Where I Am a Member
let query = FeedsQuery(
filter: .contains(.members, "john")
)
let feedList = client.feedList(for: query)
let feeds = try await feedList.get()
val query = FeedsQuery(
filter = FeedsFilterField.members.contains("john")
)
val feedList = client.feedList(query = query)
val feeds: Result<List<FeedData>> = feedList.get()
await client.queryFeeds({
filter: {
members: { $in: ["john"] },
},
});
const query = FeedsQuery(
filter: Filter.contains(FeedsFilterField.members, 'john'),
);
final feedList = client.feedList(query);
final feeds = await feedList.get();
await client.feeds.queryFeeds({
filter: {
members: { $in: ["john"] },
},
});
ctx := context.Background()
filter := map[string]any{
"members": map[string]any{
"$in": []string{"john"},
},
}
response, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: filter,
})
if err != nil {
log.Fatal("Error querying feeds:", err)
}
log.Printf("Query feeds response: %+v", response)
Map<String, Object> filter = new HashMap<>();
Map<String, Object> membersFilter = new HashMap<>();
membersFilter.put("$in", List.of("john"));
filter.put("members", membersFilter);
QueryFeedsRequest request = QueryFeedsRequest.builder()
.filter(filter)
.build();
QueryFeedsResponse response = feeds.queryFeeds(request).execute().getData();
$response = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)[
'members' => (object)['$in' => ['john']]
]
)
);
var response = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new
{
members = new { __in = new[] { "john" } }
}
}
);
response = feeds.query_feeds(
filter={
"members": {"$in": ["john"]}
}
)
response = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: {
"members" => { "$in" => ["john"] }
}
)
)
Querying feeds by name or visibility
let sportsQuery = FeedsQuery(
filter: .and([
.equal(.visibility, "public"),
.query(.name, "Sports")
])
)
let sportsFeedList = client.feedList(for: sportsQuery)
let sportsFeeds = try await sportsFeedList.get()
let techQuery = FeedsQuery(
filter: .and([
.equal(.visibility, "public"),
.autocomplete(.description, "tech")
])
)
let techFeedList = client.feedList(for: techQuery)
let techFeeds = try await techFeedList.get()
val sportsQuery = FeedsQuery(
filter = Filters.and(
FeedsFilterField.visibility.equal("public"),
FeedsFilterField.name.query("Sports")
)
)
val sportsFeedList = client.feedList(query = sportsQuery)
val sportsFeeds: Result<List<FeedData>> = sportsFeedList.get()
val techQuery = FeedsQuery(
filter = Filters.and(
FeedsFilterField.visibility.equal("public"),
FeedsFilterField.description.autocomplete("tech")
)
)
val techFeedList = client.feedList(query = techQuery)
val techFeeds: Result<List<FeedData>> = techFeedList.get()
await client.queryFeeds({
filter: {
visibility: { $eq: "public" },
name: { $q: "Sports" },
},
});
// search public feeds by description
await client.queryFeeds({
filter: {
// Shorthand for the $eq operator
visibility: "public",
description: { $autocomplete: "tech" },
},
});
const sportsQuery = FeedsQuery(
filter: Filter.and([
Filter.equal(FeedsFilterField.visibility, 'public'),
Filter.query(FeedsFilterField.name, 'Sports'),
]),
);
final sportsFeedList = client.feedList(sportsQuery);
final sportsFeeds = await sportsFeedList.get();
const techQuery = FeedsQuery(
filter: Filter.and([
Filter.equal(FeedsFilterField.visibility, 'public'),
Filter.autoComplete(FeedsFilterField.description, 'tech'),
]),
);
final techFeedList = client.feedList(techQuery);
final techFeeds = await techFeedList.get();
await client.feeds.queryFeeds({
filter: {
visibility: { $eq: "public" },
name: { $q: "Sports" },
},
});
// search public feeds by description
await client.feeds.queryFeeds({
filter: {
// Shorthand for the $eq operator
visibility: "public",
description: { $autocomplete: "tech" },
},
});
// Create context
ctx := context.Background()
response1, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: map[string]any{
"visibility": map[string]any{
"$eq": "public",
},
"name": map[string]any{
"$q": "Sports",
},
},
})
if err != nil {
log.Fatal("Error querying feeds:", err)
}
log.Printf("Query feeds response 1: %+v", response1)
response2, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: map[string]any{
"visibility": getstream.PtrTo("public"),
"description": map[string]any{
"$autocomplete": "tech",
},
},
})
// Search public feeds by name
Map<String, Object> filter1 = new HashMap<>();
filter1.put("visibility", Map.of("$eq", "public"));
filter1.put("name", Map.of("$q", "Sports"));
QueryFeedsRequest request1 = QueryFeedsRequest.builder()
.filter(filter1)
.build();
QueryFeedsResponse response1 = feeds.queryFeeds(request1).execute().getData();
// Search public feeds by description
Map<String, Object> filter2 = new HashMap<>();
filter2.put("visibility", "public");
filter2.put("description", Map.of("$autocomplete", "tech"));
QueryFeedsRequest request2 = QueryFeedsRequest.builder()
.filter(filter2)
.build();
QueryFeedsResponse response2 = feeds.queryFeeds(request2).execute().getData();
// Search public feeds by name
$response = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)[
'visibility' => (object)['$eq' => 'public'],
'name' => (object)['$q' => 'Sports']
]
)
);
// Search public feeds by description
$response2 = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)[
'visibility' => 'public',
'description' => (object)['$autocomplete' => 'tech']
]
)
);
// Search public feeds by name
var response1 = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new
{
visibility = new { __eq = "public" },
name = new { __q = "Sports" }
}
}
);
// Search public feeds by description
var response2 = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new
{
visibility = "public",
description = new { __autocomplete = "tech" }
}
}
);
# Search public feeds by name
response1 = feeds.query_feeds(
filter={
"visibility": {"$eq": "public"},
"name": {"$q": "Sports"}
}
)
# Search public feeds by description
response2 = feeds.query_feeds(
filter={
"visibility": "public",
"description": {"$autocomplete": "tech"}
}
)
# Search public feeds by name
response1 = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: {
"visibility" => { "$eq" => "public" },
"name" => { "$q" => "Sports" }
}
)
)
# Search public feeds by description
response2 = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: {
"visibility" => "public",
"description" => { "$autocomplete" => "tech" }
}
)
)
Querying feeds by creator name
let query = FeedsQuery(
filter: .and([
.equal(.visibility, "public"),
.query(.createdByName, "Thompson")
])
)
let feedList = client.feedList(for: query)
let feeds = try await feedList.get()
val query = FeedsQuery(
filter = Filters.and(
FeedsFilterField.visibility.equal("public"),
FeedsFilterField.createdByName.query("Thompson"),
)
)
val feedList = client.feedList(query = query)
val feeds: Result<List<FeedData>> = feedList.get()
// search public feeds created by users with 'Thompson' in their name
await client.queryFeeds({
filter: {
visibility: "public",
"created_by.name": { $q: "Thompson" },
},
});
const query = FeedsQuery(
filter: Filter.and([
Filter.equal(FeedsFilterField.visibility, 'public'),
Filter.query(FeedsFilterField.createdByName, 'Thompson'),
]),
);
final feedList = client.feedList(query);
final feeds = await feedList.get();
// search public feeds created by users with 'Thompson' in their name
await client.feeds.queryFeeds({
filter: {
visibility: "public",
"created_by.name": { $q: "Thompson" },
},
});
// Create context
ctx := context.Background()
// Search public feeds created by users with 'Thompson' in their name
if response, err := client.Feeds().QueryFeeds(ctx, &getstream.QueryFeedsRequest{
Filter: map[string]any{
"visibility": "public",
"created_by.name": map[string]any{
"$q": "Thompson",
},
},
});
err != nil {
log.Fatal("Error querying feeds:", err)
} else {
log.Printf("Found %d feeds", len(response.Data.Feeds))
}
// Search public feeds created by users with 'Thompson' in their name
Map<String, Object> filter = new HashMap<>();
filter.put("visibility", "public");
filter.put("created_by.name", Map.of("$q", "Thompson"));
QueryFeedsRequest request = QueryFeedsRequest.builder()
.filter(filter)
.build();
QueryFeedsResponse response = feeds.queryFeeds(request).execute().getData();
$response = $feedsClient->queryFeeds(
new GeneratedModels\QueryFeedsRequest(
filter: (object)[
'visibility' => 'public',
'created_by.name' => (object)['$q' => 'Thompson']
]
)
);
var response = await _feedsV3Client.QueryFeedsAsync(
request: new QueryFeedsRequest
{
Filter = new
{
visibility = "public",
created_by = new { name = new { __q = "Thompson" } }
}
}
);
response = feeds.query_feeds(
filter={
"visibility": "public",
"created_by.name": {"$q": "Thompson"}
}
)
response = client.feeds.query_feeds(
GetStream::Generated::Models::QueryFeedsRequest.new(
filter: {
"visibility" => "public",
"created_by.name" => { "$q" => "Thompson" }
}
)
)
Feeds Queryable Built-in Fields
name | type | description | supported operations | example |
---|---|---|---|---|
id | string or list of strings | The ID of the feed | $in , $eq | { id: { $in: [ 'abc', 'xyz' ] } } |
group_id | string or list of strings | The ID of the group this feed belongs to | $in , $eq | { group_id: { $in: [ 'abc', 'xyz' ] } } |
feed | string or list of strings | The fully qualified feed ID (group_id:id) | $in , $eq | { fid: { $in: [ 'abc', 'xyz' ] } } |
visibility | string or list of strings | The visibility setting of the feed | $in , $eq | { visibility: { $eq: 'public' } } |
created_by_id | string or list of strings | The ID of the user who created the feed | $in , $eq | { created_by_id: { $in: [ 'abc', 'xyz' ] } } |
created_by.name | string | The name of the user who created the feed | $eq , $q , $autocomplete | { 'created_by.name': { $autocomplete: 'Frank' } } |
name | string | The name of the feed | $eq , $q , $autocomplete | { name: { $q: 'Sports' } } |
description | string | The description of the feed | $eq , $q , $autocomplete | { description: { $autocomplete: 'tech' } } |
member_count | number | The number of members in this feed | $eq , $ne , $gt , $lt , $gte , $lte | { member_count: { $gt: 100 } } |
members | list of strings | The list of members in this feed | $in | { members: { $in: [ 'bob', 'alice' ] } } |
following_count | number | The number of feeds this feed follows | $eq , $ne , $gt , $lt , $gte , $lte | { following_count: { $gt: 100 } } |
following_feeds | list of strings | The list of feeds this feed follows | $in | { following_feeds: { $in: [ 'feed1', 'feed2' ] } } |
follower_count | number | The number of followers of this feed | $eq , $ne , $gt , $lt , $gte , $lte | { follower_count: { $gt: 100 } } |
created_at | string, RFC3339 timestamp | The time the feed was created | $eq , $gt , $lt , $gte , $lte | { created_at: { $gte: '2023-12-04T09:30:20.45Z' } } |
updated_at | string, RFC3339 timestamp | The time the feed was updated | $eq , $gt , $lt , $gte , $lte | { updated_at: { $gte: '2023-12-04T09:30:20.45Z' } } |
filter_tags | list of strings | Tags for filtering the feed | $eq , $contains , $in | { filter_tags: { $in: [ 'sports', 'news' ] } } |
Feeds can be sorted by created_at
, updated_at
, member_count
, follower_count
, and following_count
.
Be sure to reach out to support if you need additional query feed capabilities.
Query Feed Members
You can query the members of a feed. This is useful for showing the list of members in a community.
val memberList = client.memberList(
MembersQuery(
fid = FeedId(group = "stock", id = "apple"),
filter = MembersFilterField.role.equal("moderator"),
)
)
memberList.get()
memberList.state.members.collect { members ->
// Handle members
}
$response = $feedsClient->queryFeedMembers('stock', 'apple', new GeneratedModels\QueryFeedMembersRequest(
filter: (object)[
'role' => 'moderator'
]
));
Feed Members Queryable Built-in Fields
name | type | description | supported operations | example |
---|---|---|---|---|
user_id | string or list of strings | The ID of the user who is a member of the feed | $in , $eq | { user_id: { $eq: 'user_123' } } |
role | string or list of strings | The role of the member | $in , $eq | { role: { $in: [ 'admin', 'moderator', 'member' ] } } |
status | string or list of strings | The membership status | $in , $eq | { status: { $in: [ 'member', 'pending', 'rejected' ] } } |
created_at | string, must be formatted as an RFC3339 timestamp | The time the membership was created | $eq , $gt , $gte , $lt , $lte | { created_at: { $gte: '2023-12-04T09:30:20.45Z' } } |
updated_at | string, must be formatted as an RFC3339 timestamp | The time the membership was last updated | $eq , $gt , $gte , $lt , $lte | { updated_at: { $gte: '2023-12-04T09:30:20.45Z' } } |