Variable-sized result when using Filter/Reduce in Paginate

Doing:

Filter(
  Map(
    Paginate(
      Match(
        Index("userGoalsBySortOrder"),
        CurrentIdentity()
      )
    ),
    Lambda(
      ["sortOrder", "ref"],
      Get(Var("ref"))
    )
  ),
  Lambda(
    ["doc"],
    Not(
      ContainsPath(
        ["data", "deletedAt"],
        Var("doc")
      )
    )
  )
)

will return variable-sized pages. Based on reply in Getting Error: Lambda expects an array with 3 elements. Array contains 1 - #4 by wallslide I can do Filter before Paginate but I’m not sure how to approach that as Match will return the fields stored in the index rather than the whole document. So I end up with:

Map(
  Paginate(
    Filter(
      Match(
        Index("userGoalsBySortOrder"),
        CurrentIdentity()
      ),
      Lambda(
        ["data", "ref"],
        Not(
          ContainsPath(
            ["data", "deletedAt"],
            Get(Var("ref"))
          )
        )
      )
    )
  ),
  Lambda(
    ["sortOrder", "ref"],
    Get(Var("ref"))
  )
)

Notice the multiple to Get(Var("ref")), I needed to get it twice and also the need for 2 loops Filter and then Map

I also tried:

Paginate(
  Reduce(
    Lambda(
      ["result", "data"],
      Let(
        {
          doc: Get(
            Select([1], Var("data"))
          )
        },
        If(
          ContainsPath(
            ["data", "deletedAt"],
            Var("doc")
          ),
          Var("result"),
          Append(
            Var("doc"),
            Var("result")
          )
        )
      )
    ),
    [],
    Match(
      Index("userGoalsBySortOrder"),
      Ref(Collection("users"), "322014450218434627")
    )
  )
)

But it throws an error:

Error: [
  {
    "position": [
      "paginate"
    ],
    "code": "invalid argument",
    "description": "Ref or Set expected, Array provided."
  }
]

I think because Reduce is returning an array rather than @set pointer for Paginate.

Other than having to use multiple Gets when the Filter call is inside the Paginate call, was there a problem with the query?

Fauna caches reads involved in a query, so you only consume read ops when a document has to be retrieved from storage. Compare these two queries:

> Do([
  Get(Ref(Collection("People"), "323144130390655488")),
  Get(Ref(Collection("People"), "323144130390655488"))
])
Query metrics:   142 bytesIn,      490 bytesOut,      12 queryTime, 
                   1 readOps,        0 writeOps,       1 computeOps,
                 114 readBytes,      0 writeBytes,     0 retries

and:

> Do([
  Get(Ref(Collection("People"), "323144130390655488")),
  Get(Ref(Collection("People"), "323144130394849792"))
])
Query metrics:   142 bytesIn,      496 bytesOut,      10 queryTime, 
                   2 readOps,        0 writeOps,       1 computeOps,
                 231 readBytes,      0 writeBytes,     0 retries

The first query reads the same document twice. The second reads two documents. The first consumes 1 read op, the second 2.

Nothing else really, other than I was concerned it might consume 2x read ops and was looking for advice if there’s a better approach. Thanks for that clarification on the read ops!