Remove null values from an array in a UDF

I have a function that returns an array of distinct string values though want to figure out how to drop a null value which is inherently included within the returned array. Can anyone help rewrite the UDF below to assist?

The v4 function is below:

Query(
  Lambda(
    [],
    Union(
      Select(
        ["data"],
        Paginate(Distinct(Match(Index("allAllergens"))), { size: 100000 })
      )
    )
  )
)

Hi @Darryl_Naidu!

There is a few things going on here, so it will be hard to know how to answer. Can you share the index definition, so we can see the shape of results? Please also provide an example document that would match the index.

Some initial considerations:

  • You’ll want to also port the index over to v10. Seeing the v4 definition we can see how to do that.
  • Union here looks like you just need that to flatten results. You can use flatmap or flatten if necessary in v10 for that.
  • you can drop a value from an array by using .where(x => x != null). But it’s not clear at all what the data looks like to start. Maybe there is something we can do with the index, or leverage a computed field, to simplify things.

Thanks @ptpaterson,

I have actually solved this with a Filter expression which I hope is reasonably efficient. The revision is below:

{
  name: "FindAllAllergens",
  role: null,
  body: Query(
    Lambda(
      [],
      Filter(
        Union(
          Select(
            ["data"],
            Paginate(Distinct(Match(Index("allAllergens"))), { size: 100000 })
          )
        ),
        Lambda("i", IsString(Var("i")))
      )
    )
  )
}

If anyone could help with a v10 conversion for this expression that would be a great help. The v10 equivalent index used is below:

index allAllergens {
    values [.allergens, .potential_allergens]
  }

What is the allAllergens v4 index definition? It looks like you are only checking if the first value defined in the v4 index is a string. Are you not concerned about the second value? And is it the same order as the values defined in the v10 definition? Just making sure :slight_smile:

You might try something like this as a v10 equivalent:

Allergens.allAllergens()
  .fold([], (acc, val) => acc.concat(val.allergens).concat(val.potential_allergens))
  .where(a => a isa String)
  .distinct()

See docs for the isa operator. Operators - Fauna Docs

And this related topic regarding that fold operation:

Thanks @ptpaterson! This works exactly as intended. Compute ops significantly reduced by re-writing the UDF as:
Allergens.allAllergens() .fold([], (acc, val) => acc.concat(val.allergens).concat(val.potential_allergens)) .distinct() .where(a => a isa String)

Now to find a less hungry alternative for fold