// 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()Create and Read Feeds
Creating a Feed
When using server-side SDKs, the user_id parameter is required in the getOrCreate request. It’s needed in order to automatically create a user. Client-side SDKs do not require this parameter as the user is authenticated via token.
// 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.membersval feed = client.feed(group = "user", id = "john")
feed.getOrCreate()
val feedData = feed.state.feed
val activities = feed.state.activities
val members = feed.state.membersconst 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.MemberstestFeed = 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.membersThe 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.feedval 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.feedconst 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.activitiesval 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.activitiesconst 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
)Filters
filter provides a performant way to read a feed, and only select activities that match a given filter.
Please note that filtering is typically used for fields with fixed value sets (for example filter_tags), for text based search, you should check out query activities endpoint
Examples
// 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 secondconst feed = client.feed("user", "123", {
// WebSocket events are delivered regardless of filters, you can filter them by providing activityAddedEventFilter
activityAddedEventFilter: (event) =>
event.activity.filter_tags.includes("blue"),
});
// 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({
watch: true,
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"
)
)Supported filters
What filters you can use when reading a feed depends on the feed group (or view, if provided) configuration.
The activity selectors page explains this in detail, but some quick examples: the user group uses current selector, and the timeline group the following selector by default.
The following filter options are available for the following selector:
| name | type | description | supported operations | example |
|---|---|---|---|---|
id | string or list of strings | The ID of the activity | $in, $eq | { id: { $in: [ 'abc', 'xyz' ] } } |
filter_tags | list of strings | Tags for filtering | $eq, $contains | { filter_tags: { $in: [ 'categoryA', 'categoryB' ] } } |
The following filter options are available for the current, popular, interest, proximity and query selectors:
| name | type | description | supported operations | example |
|---|---|---|---|---|
id | string or list of strings | The ID of the activity | $in, $eq | { id: { $in: [ 'abc', 'xyz' ] } } |
activity_type | string or list of strings | The type of the activity | $in, $eq | { activity_type: { $in: [ 'abc', 'xyz' ] } } |
user_id | string or list of strings | The ID of the user who created the activity | $in, $eq | { user_id: { $in: [ 'abc', 'xyz' ] } } |
text | string | The text content of the activity | $eq, $q, $autocomplete | { text: { $q: 'popularity' } } |
search_data | object | The extra metadata for search indexing | $contains, $path_exists | { search_data: { $contains: { 'category': 'sports', 'status': 'active' } } } |
interest_tags | list of strings | Tags for user interests | $eq, $contains | { interest_tags: { $in: [ 'sports', 'music' ] } } |
filter_tags | list of strings | Tags for filtering | $eq, $contains | { filter_tags: { $in: [ 'categoryA', 'categoryB' ] } } |
created_at | string, must be formatted as an RFC3339 timestamp | The time the activity was created | $eq, $gt, $lt, $gte, $lte | { created_at: { $gte: '2023-12-04T09:30:20.45Z' } } |
popularity | number | The popularity score of the activity | $eq, $ne, $gt, $lt, $gte, $lte | { popularity: { $gte: 70 } } |
near | object | Indicates the GEO point to search nearby activities. | $eq | { near: { $eq: { lat: 40.0, lng: -74.0, distance: 200 } } } |
within_bounds | object | Indicates the GEO bounds to search for activities within. | $eq | { within_bounds: { $eq: { ne_lat: 40.0, ne_lng: -115.0, sw_lat: 32.0, sw_lng: -125.0 } } } |
The filter syntax also supports $or and $and:
// Get all the activities where filter tags contain both "green" and "orange"
let filter = .and([
.in(.filterTags, ["green"]),
.in(.filterTags, ["orange"])
])// Get all the activities where filter tags contain both "green" and "orange"
val filter = Filters.and(
ActivitiesFilterField.filterTags.`in`("green"),
ActivitiesFilterField.filterTags.`in`("orange"),
)// Get all the activities where filter tags contain both "green" and "orange"
const filter = {
$and: [{ filter_tags: ["green"] }, { filter_tags: ["orange"] }],
};// Get all the activities where filter tags contain both "green" and "orange"
const filter = Filter.and([
Filter.in_(ActivitiesFilterField.filterTags, ['green']),
Filter.in_(ActivitiesFilterField.filterTags, ['orange']),
])// Get all the activities where filter tags contain both "green" and "orange"
const filter = {
$and: [
{ filter_tags: ["green"] }
{ filter_tags: ["orange"] }
],
}// Get all the activities where filter tags contain both "green" and "orange"
filter := map[string]any{
"$and": []map[string]any{
{"filter_tags": []string{"green"}},
{"filter_tags": []string{"orange"}},
},
}// 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);$filter = (object)['and' => [
'filter_tags' => ['green'],
'filter_tags' => ['orange'],
]]// Get all the activities where filter tags contain both "green" and "orange"
var filter = = new
{
and = new[]
{
new { filter_tags = new[] { "green" } },
new { filter_tags = new[] { "orange" } }
}
}# Get all the activities where filter tags contain both "green" and "orange"
filter = {
"$and": [
{"filter_tags": ["green"]},
{"filter_tags": ["orange"]}
]
}# Get all the activities where filter tags contain both "green" and "orange"
filter = {
"$and" => [
{ "filter_tags" => ["green"] },
{ "filter_tags" => ["orange"] }
]
}When providing filter to read a feed, activity selector filters on group/view level are ignored.
Overview of built-in fields
GetOrCreateFeedResponse
| Name | Type | Description | Constraints |
|---|---|---|---|
activities | ActivityResponse[] | - | Required |
aggregated_activities | AggregatedActivityResponse[] | - | Required |
created | boolean | - | Required |
duration | string | Duration of the request in milliseconds | Required |
feed | FeedResponse | - | Required |
followers | FollowResponse[] | - | Required |
followers_pagination | PagerResponse | - | - |
following | FollowResponse[] | - | Required |
following_pagination | PagerResponse | - | - |
member_pagination | PagerResponse | - | - |
members | FeedMemberResponse[] | - | Required |
next | string | - | - |
notification_status | NotificationStatusResponse | - | - |
pinned_activities | ActivityPinResponse[] | - | Required |
prev | string | - | - |
FeedResponse
| Name | Type | Description | Constraints |
|---|---|---|---|
created_at | number | When the feed was created | Required |
created_by | UserResponse | User who created the feed | Required |
custom | object | Custom data for the feed | - |
deleted_at | number | When the feed was deleted | - |
description | string | Description of the feed | Required |
feed | string | Fully qualified feed ID (group_id:id) | Required |
filter_tags | string[] | Tags used for filtering feeds | - |
follower_count | integer | Number of followers of this feed | Required |
following_count | integer | Number of feeds this feed follows | Required |
group_id | string | Group this feed belongs to | Required |
id | string | Unique identifier for the feed | Required |
member_count | integer | Number of members in this feed | Required |
name | string | Name of the feed | Required |
own_capabilities | FeedOwnCapability[] | Capabilities the current user has for this feed | - |
own_follows | FollowResponse[] | Follow relationships where the current user's feeds are following this feed | - |
own_membership | FeedMemberResponse | Membership information for the current user in this feed | - |
pin_count | integer | Number of pinned activities in this feed | Required |
updated_at | number | When the feed was last updated | Required |
visibility | string | Visibility setting for the feed | - |