Join

Copied!
( source, target )

Description

The Join function joins the source set’s tuples with the target. target can be one of:

  • An index Reference.

    The source set’s tuples are iterated, and an implicit Match call is made for each tuple against the target index’s terms. The union of the results is returned.

  • A Lambda function.

    The source set’s tuples are iterated and passed to the function. The function decides how each tuple should be handled. The union of the results is returned.

    The Lambda function must be pure: it must not create side effects, such as any additional reads or writes.

In either case, if the source set’s tuples do not match the number and types of the target, an error occurs.

Parameters

Parameter Type Definition and Requirements

source

The source Set Reference for the join operation.

target

An index Reference or Lambda function

The index Reference to join with the source Set Reference, or the Lambda function which determines how to complete the join operation.

Returns

The Set Reference for the union of the results from the join operation.

Examples

  1. The following query joins the "spellbooks" documents for a specific owner with the "spells_by_spellbook" index, which reports the spells for each spellbook, answering the question "what spells can this owner cast?":

    Copied!
    (
      (
        (
          (
            ('spellbooks_by_owner'),
            (('characters'), '181388642114077184')
          ),
          ('spells_by_spellbook'),
        )
      ),
      ("ref", (("ref")))
    )
    {
      data: [
        {
          ref: (("spells"), "181388642046968320"),
          ts: 1626225336060000,
          data: {
            name: 'Fire Beak',
            element: [ 'air', 'fire' ],
            spellbook: (("spellbooks"), "181388642139243008")
          }
        },
        {
          ref: (("spells"), "181388642071085568"),
          ts: 1626225336060000,
          data: {
            name: "Water Dragon's Claw",
            element: [ 'water', 'fire' ],
            spellbook: (("spellbooks"), "181388642139243008")
          }
        }
      ]
    }
    Query metrics:
    •    bytesIn:  239

    •   bytesOut:  705

    • computeOps:    1

    •    readOps:    3

    •   writeOps:    0

    •  readBytes:  418

    • writeBytes:    0

    •  queryTime: 18ms

    •    retries:    0

  2. The following query joins the "spellbooks" documents for a specific owner with a Lambda function, which performs the equivalent "spells_by_spellbook" lookup as the previous query example:

    Copied!
    (
      (
        (
          (
            ('spellbooks_by_owner'),
            (('characters'), '181388642114077184'),
          ),
          (
            'spellbook',
            (('spells_by_spellbook'), ('spellbook')),
          )
        )
      ),
      ("ref", (("ref")))
    )
    {
      data: [
        {
          ref: (("spells"), "181388642046968320"),
          ts: 1626221552780000,
          data: {
            name: 'Fire Beak',
            element: [ 'air', 'fire' ],
            spellbook: (("spellbooks"), "181388642139243008")
          }
        },
        {
          ref: (("spells"), "181388642071085568"),
          ts: 1626221552780000,
          data: {
            name: "Water Dragon's Claw",
            element: [ 'water', 'fire' ],
            spellbook: (("spellbooks"), "181388642139243008")
          }
        }
      ]
    }
    Query metrics:
    •    bytesIn:  307

    •   bytesOut:  705

    • computeOps:    1

    •    readOps:    3

    •   writeOps:    0

    •  readBytes:  418

    • writeBytes:    0

    •  queryTime: 12ms

    •    retries:    0

  3. The following query uses the Lambda variant of Join to answer the question "What are the inventory levels for the products in a particular store?".

    This question cannot be directly answered using the index variant of Join because the "products_by_store" index returns each product’s name, description, and price, and the "inventory_by_product" index uses only the product’s name in its terms definition (a mismatch in tuple sizes). The Lambda function calls Match with just the name value to resolve the mismatch:

    Copied!
    (
      (
        (
          ('products_by_store'),
          (('stores'), '301'),
        ),
        (
          ['name', 'description', 'price'],
          (('inventory_by_product'), ('name'))
        )
      )
    )
    {
      data: [
        [
          1000,
          'Conventional Hass, 4ct bag',
          (("products"), "204")
        ],
        [ 1000, 'Conventional, 1 ct', (("products"), "205") ],
        [ 100, 'Organic, 1 bunch', (("products"), "208") ],
        [ 50, 'Organic, 16 oz bag', (("products"), "206") ],
        [
          30,
          'Conventional, 16 oz bag',
          (("products"), "207")
        ]
      ]
    }
    Query metrics:
    •    bytesIn:  234

    •   bytesOut:  694

    • computeOps:    1

    •    readOps:    1

    •   writeOps:    0

    •  readBytes:  811

    • writeBytes:    0

    •  queryTime: 24ms

    •    retries:    0

The run time of Join is dependent on the number of elements in the underlying set or page — it’s linear, or O(n). For very large sets or pages, executing Join might result in a query timeout error, or "width" error.

For query "width" errors, the underlying set or page involves more than 100K items. This can happen when using a set function, such as Difference, where more than 100K items need to be considered to produce the set that Join evaluates. To resolve this, use Paginate to limit the set or page size.

For example, instead of:

shellCopied!
(
  (
    (("Index1"), "term1"),
    (("Index2"), "term2")
  ),
  ("Index3")
)

use:

shellCopied!
(
  (
    (
      (("Index1"), "term1"),
      (("Index2"), "term2")
    ),
    { size: 10000 }
  ),
  ("Index3")
)

This does mean that if the entire set must be evaluated to arrive at the correct result, you would have to page through the Paginate results.

For query timeout errors, you may specify a larger query timeout via the driver that you are using.

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!