List of terms using a UDF

Problem

You want to search an index using a list of terms but the number of terms is dynamic.

Solution

This is a more advanced version of the List of terms solution. This solution uses a user-defined function (UDF) to compose the query for every provided term.

Copied!
({
  name: "search_spells",
  body: (
    (
      "terms",
      (
        {
          term_array: (
            (
              ["acc", "val"],
              (
                [ (("spells_by_element"), ("val")) ],
                ("acc")
              )
            ),
            [],
            ("terms")
          ),
          search_set: (
            ((("term_array")), 0),
            (("term_array")),
            (("spells"))
          )
        },
        ((("search_set")), ("ref", (("ref"))))
      )
    )
  )
})
Query metrics:
  •    bytesIn:  563

  •   bytesOut:  661

  • computeOps:    1

  •    readOps:    0

  •   writeOps:    1

  •  readBytes:   26

  • writeBytes:  704

  •  queryTime: 33ms

  •    retries:    0

You can now call the UDF with an array of terms to search:

Copied!
(("search_spells"), ["earth"])
{
  data: [
    {
      ref: (("spells"), "181388642088911360"),
      ts: 1629503268260000,
      data: { name: "Hippo's Wallow", element: [ 'water', 'earth' ] }
    }
  ]
}
Query metrics:
  •    bytesIn:   59

  •   bytesOut:  232

  • computeOps:    1

  •    readOps:    2

  •   writeOps:    0

  •  readBytes:  162

  • writeBytes:    0

  •  queryTime: 13ms

  •    retries:    0

or with a different array:

Copied!
(("search_spells"), ["earth", "fire"])
{
  data: [
    {
      ref: (("spells"), "181388642046968320"),
      ts: 1629830703650000,
      data: {
        name: 'Fire Beak',
        element: [ 'air', 'fire' ],
        spellbook: (("spellbooks"), "181388642139243008")
      }
    },
    {
      ref: (("spells"), "181388642071085568"),
      ts: 1629830703650000,
      data: {
        name: "Water Dragon's Claw",
        element: [ 'water', 'fire' ],
        spellbook: (("spellbooks"), "181388642139243008")
      }
    },
    {
      ref: (("spells"), "181388642088911360"),
      ts: 1629830703650000,
      data: { name: "Hippo's Wallow", element: [ 'water', 'earth' ] }
    }
  ]
}
Query metrics:
  •    bytesIn:   66

  •   bytesOut:  914

  • computeOps:    1

  •    readOps:    5

  •   writeOps:    0

  •  readBytes:  503

  • writeBytes:    0

  •  queryTime: 13ms

  •    retries:    0

Discussion

You pass an array of terms in the Call function and the UDF uses Reduce to compose a Match expression for each term. When there are terms, a Union of the results is returned, otherwise the list of documents in the spells collection is returned.

Union combines all of the results for every term, which is equivalent to an "or" query. If you replace Union with Intersection, only the results common to every term are returned, which is equivalent to an "and" query.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!