@@ -194,91 +194,126 @@ func fetchColumnData(client *firestore.Client, path string, isDoc bool, columnIn
194194 colPath := strings .TrimPrefix (path , "/" )
195195 colRef := client .Collection (colPath )
196196
197- // Apply sorting if specified
198- query := colRef .Query
199- if fo .query != nil {
200- query = query .Where (fo .query .Field , fo .query .Operator , fo .query .Value )
201- }
202- if sortField != "" {
203- query = query .OrderBy (sortField , sortDirection )
204- }
205-
206- // Apply pagination limit
207- if fo .limit > 0 {
208- query = query .Limit (fo .limit + 1 ) // Fetch one extra to detect hasMore
209- if fo .offset > 0 {
210- query = query .Offset (fo .offset )
211- }
212- }
213-
214- iter := query .Documents (ctx )
215197 var items []ListItem
216198 firstDoc := true
217- fetchCount := 0
218- for {
219- doc , err := iter .Next ()
220- if err == iterator .Done {
221- break
222- }
223- if err != nil {
224- return errorMsg {err : err }
199+
200+ if fo .query == nil && sortField == "" {
201+ // The default collection view should include both stored documents and
202+ // document refs that only exist because they have subcollections.
203+ refsIter := colRef .DocumentRefs (ctx )
204+ refs := []* firestore.DocumentRef {}
205+ skipped := 0
206+ for {
207+ ref , err := refsIter .Next ()
208+ if err == iterator .Done {
209+ break
210+ }
211+ if err != nil {
212+ return errorMsg {err : err }
213+ }
214+ if skipped < fo .offset {
215+ skipped ++
216+ continue
217+ }
218+ if fo .limit > 0 && len (refs ) > fo .limit {
219+ hasMore = true
220+ break
221+ }
222+ refs = append (refs , ref )
225223 }
226224
227- fetchCount ++
228- // If we got more than limit, we have more pages
229- if fo .limit > 0 && fetchCount > fo .limit {
225+ if fo .limit > 0 && len (refs ) > fo .limit {
230226 hasMore = true
231- break
227+ refs = refs [: fo . limit ]
232228 }
233229
234- // Extract field names from first document
235- if firstDoc {
236- firstDoc = false
237- data := doc .Data ()
238- for key := range data {
239- availableFields = append (availableFields , key )
230+ if len (refs ) > 0 {
231+ snaps , err := client .GetAll (ctx , refs )
232+ if err != nil {
233+ return errorMsg {err : err }
234+ }
235+
236+ for _ , snap := range snaps {
237+ docPath := path + "/" + snap .Ref .ID
238+ item := ListItem {
239+ id : snap .Ref .ID ,
240+ path : docPath ,
241+ isDoc : true ,
242+ }
243+ if snap .Exists () {
244+ if firstDoc {
245+ firstDoc = false
246+ data := snap .Data ()
247+ for key := range data {
248+ availableFields = append (availableFields , key )
249+ }
250+ sort .Strings (availableFields )
251+ }
252+
253+ metadata := map [string ]string {}
254+ if ! snap .CreateTime .IsZero () {
255+ metadata ["created" ] = snap .CreateTime .Local ().Format ("2006-01-02 15:04:05" )
256+ }
257+ item .metadata = metadata
258+ } else {
259+ item .isMissing = true
260+ }
261+ items = append (items , item )
240262 }
241- sort .Strings (availableFields )
242263 }
243-
244- metadata := map [string ]string {}
245- if ! doc .CreateTime .IsZero () {
246- metadata ["created" ] = doc .CreateTime .Local ().Format ("2006-01-02 15:04:05" )
264+ } else {
265+ // Queries and sorts must use Firestore's server-side document query.
266+ query := colRef .Query
267+ if fo .query != nil {
268+ query = query .Where (fo .query .Field , fo .query .Operator , fo .query .Value )
269+ }
270+ if sortField != "" {
271+ query = query .OrderBy (sortField , sortDirection )
247272 }
248- docPath := path + "/" + doc .Ref .ID
249- items = append (items , ListItem {
250- id : doc .Ref .ID ,
251- path : docPath ,
252- isDoc : true ,
253- metadata : metadata ,
254- })
255- }
256273
257- // Only fetch document refs for missing docs on first page
258- if fo .offset == 0 {
259- seen := make ( map [ string ] bool , len ( items ))
260- for _ , item := range items {
261- seen [ item . id ] = true
274+ if fo . limit > 0 {
275+ query = query . Limit ( fo .limit + 1 )
276+ if fo . offset > 0 {
277+ query = query . Offset ( fo . offset )
278+ }
262279 }
263280
264- refsIter := colRef .DocumentRefs (ctx )
281+ iter := query .Documents (ctx )
282+ fetchCount := 0
265283 for {
266- ref , err := refsIter .Next ()
284+ doc , err := iter .Next ()
267285 if err == iterator .Done {
268286 break
269287 }
270288 if err != nil {
271289 return errorMsg {err : err }
272290 }
273- if seen [ref .ID ] {
274- continue
291+
292+ fetchCount ++
293+ if fo .limit > 0 && fetchCount > fo .limit {
294+ hasMore = true
295+ break
296+ }
297+
298+ if firstDoc {
299+ firstDoc = false
300+ data := doc .Data ()
301+ for key := range data {
302+ availableFields = append (availableFields , key )
303+ }
304+ sort .Strings (availableFields )
305+ }
306+
307+ metadata := map [string ]string {}
308+ if ! doc .CreateTime .IsZero () {
309+ metadata ["created" ] = doc .CreateTime .Local ().Format ("2006-01-02 15:04:05" )
275310 }
276- docPath := path + "/" + ref .ID
311+ docPath := path + "/" + doc . Ref .ID
277312 items = append (items , ListItem {
278- id : ref .ID ,
279- path : docPath ,
280- isDoc : true ,
281- isMissing : true ,
313+ id : doc . Ref .ID ,
314+ path : docPath ,
315+ isDoc : true ,
316+ metadata : metadata ,
282317 })
283318 }
284319 }
@@ -391,13 +426,13 @@ func fetchColumnData(client *firestore.Client, path string, isDoc bool, columnIn
391426 }
392427 }
393428
394- // Count queried documents (exclude missing refs and sentinel — docCount
395- // is used as the Firestore query Offset for pagination)
429+ // Count displayed documents/refs (exclude sentinel — docCount is used as
430+ // the Offset for pagination in both query and DocumentRefs modes).
396431 totalDocs := 0
397432 for _ , s := range sections {
398433 if s .title == "Documents" {
399434 for _ , item := range s .items {
400- if item .path != "__load_more__" && ! item . isMissing {
435+ if item .path != "__load_more__" {
401436 totalDocs ++
402437 }
403438 }
0 commit comments