// 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.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 )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 secondconst 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.feedsval 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.feedsconst 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' } } |