Convert array of Refs to a Set

Is there any way to convert an array of Refs to a Set?

Use case:

If a client sends an array of ids or Refs for an operation, it could be useful to use Intersection and/or other Set operations for that array with Sets in the DB.

This can kinda be done now, but it requires reading the Set and mapping to an array. If the user provided array is much smaller than the Set, then paginating the whole Set would be very wasteful.

I suppose you could use an Index by Ref and then Union those. This might actually be okay for really small user input, but sounds like it could rack up read ops quickly for each Index and Union op.

Union(
  Map([list, of, refs], ref => Match(Index('index_by_ref'), Var('ref')))
)

Any thoughts?

See also this question from @danbars , which made me think of this:

@ptpaterson Currently, we cannot, but it is a valid use case. Thanks for bringing this to our attention. I am tagging this post as a feature request so we can implement this in the future.

This is a pretty convoluted workaround, but here are some facts that let us do some cool (strange) things.

  • Set operations can except a single array of SetRefs.
  • Singleton lets us turn a Ref into a SetRef
  • You can Map over an array of Refs and turn them into an array of SetRefs
  • You can Append additional SetRefs to that array and Union/Intersection/whatever them
  • You can Union an array of Singletons into a single SetRef to use in other Set operations

example, again referencing @danbars prior question:

Paginate(
  Intersection(
    Union(
      Map(
        Var("submissionSet"), // array of id's from client
        id => Singleton(Ref(Collection("FormSubmits"), id))
      )
    ),
    Match(Index('formSubmits_by_form_and_account'), Var('formId'), Var('accountId'))
  )
)

One should be careful using Union this way though, since the cost is basically 2n Read Ops (n = number of Sets in the Union). It may ultimately be cheaper to just read all of the docs and Filter them (it would be in this example).

This is why having a single-read-op function to convert the Ref array to a Set would be huge. But this is cool IMO in any case, so maybe it can find use.

Another contrived example of adding a list of Refs to another index (with possible duplicates):

Paginate(
  Union(
    Append(
      Map(
        ["1234", "5555"],
        id => Singleton(Ref(Collection("Things"), id))
      ),
      [
        Match(Index('things_by_field'), 'value1'),
        Match(Index('things_by_field'), 'value2'),
      ]
    )
  )
)