Reduce

Reduce( reducer, initial, arrayOrSet )
Reduce( reducer, initial, arrayOrSet )
Reduce( reducer, initial, arrayOrSet )
Reduce( reducer, initial, arrayOrSet )
reduce( reducer, initial, arrayOrSet )
Not available in this language yet.
Reduce( reducer, initial, arrayOrSet )
Not available in this language yet.

Description

The Reduce function applies a reducer Lambda function serially to each member of arrayOrSet (which is an Array, Page, or Set) to produce a single value (any scalar, array, object, etc.).

When the reducer function is called, it is provided with an accumulator that represents the current state of the result, and the current item from arrayOrSet. The value that the reducer returns becomes the accumulator for the next iteration. Subsequent invocations of reducer can see the results of earlier invocations.

When Reduce starts, the accumulator is set to the initial value. When Reduce completes its processing, the current value of the accumulator is returned.

Parameters

Argument Type Definition and Requirements

reducer

The function to apply to each item in arrayOrSet.

The function must have the signature f( accumulator, value ), where:

  • accumulator is the current state of the result

  • value is the current item from arrayOrSet

The return value from the reducer function becomes the accumulator for the next iteration.

initial

Any

The initial parameter sets the initial value of the accumulator.

arrayOrSet

Array, Page, or Set

The items to be reduced.

Returns

The value of the accumulator, which would typically be the same type as the initial value.

Examples

The following query demonstrates the simplest reducer, which counts the items in arrayOrSet. It does this by adding 1 to the accumulator for each item:

Value result = await client.Query(
  Reduce(
    Lambda(Arr("acc", "value"), Add(Var("acc"), 1)),
    0,
    Arr(1, 2, 3, 4, 5)
  )
);
result, err := client.Query(
  f.Reduce(
    f.Lambda(
      f.Arr{"acc", "value"},
      f.Add(f.Var("acc"), 1),
    ),
    0,
    f.Arr{1, 2, 3, 4, 5}))
System.out.println(
    client.query(
        Reduce(
            Lambda(
                Arr(Value("acc"), Value("val")),
                Add(Var("acc"), Value(1))
            ),
            Value(0),
            Arr(Value(1), Value(2), Value(3), Value(4), Value(5))
        )
    ).get());
client.query(
  q.Reduce(
    q.Lambda((acc, value) => q.Add(acc, 1)),
    0,
    [ 1, 2, 3, 4, 5 ],
  )
)
.then((ret) => console.log(ret))
print(client.query(
  q.reduce(
    q.lambda_(["acc", "value"], q.add(q.var("acc"), 1)),
    0,
    [ 1, 2, 3, 4, 5 ],
  )
))
Not available in this language yet.
println(Await.result(
  client.query(
    Reduce(
      Lambda(Arr("acc", "val"), Add(Var("acc"), 1)),
      0,
      Arr(1, 2, 3, 4, 5)
    )
  ),
  5.seconds
))
Not available in this language yet.
5
5
5
5
5
5

The following query demonstrates how to sum the values in arrayOrSet. It does this by adding the value of each item to the accumulator:

Value result = await client.Query(
  Reduce(
    Lambda(Arr("acc", "value"), Add(Var("acc"), Var("value"))),
    0,
    Arr(1, 2, 3, 4, 5)
  )
);
result, err := client.Query(
  f.Reduce(
    f.Lambda(
      f.Arr{"acc", "value"},
      f.Add(f.Var("acc"), f.Var("value")),
    ),
    0,
    f.Arr{1, 2, 3, 4, 5}))
System.out.println(
    client.query(
        Reduce(
            Lambda(
                Arr(Value("acc"), Value("value")),
                Add(Var("acc"), Var("value"))
            ),
            Value(0),
            Arr(Value(1), Value(2), Value(3), Value(4), Value(5))
        )
    ).get());
client.query(
  q.Reduce(
    q.Lambda((acc, value) => q.Add(acc, value)),
    0,
    [ 1, 2, 3, 4, 5 ]
  )
)
.then((ret) => console.log(ret))
print(client.query(
  q.reduce(
    q.lambda_(["acc", "value"], q.add(q.var("acc"), q.var("value"))),
    0,
    [ 1, 2, 3, 4, 5 ],
  )
))
Not available in this language yet.
println(Await.result(
  client.query(
    Reduce(
      Lambda(Arr("acc", "value"), Add(Var("acc"), Var("value"))),
      0,
      Arr(1, 2, 3, 4, 5)
    )
  ),
  5.seconds
))
Not available in this language yet.
15
15
15
15
15
15

The following query demonstrates how to count, sum, and compute the minimum and maximum values, plus the average. This time, our accumulator is an object with multiple keys, and our Lambda function now performs all of those calculations:

Value result = await client.Query(
  Reduce(
    Lambda(
      Arr("acc", "value"),
      Let(
        "count", Add(Select("count", Var("acc")), 1),
        "total", Add(Select("total", Var("acc")), Var("value")),
        "min", Select("min", Var("acc")),
        "max", Select("max", Var("acc"))
      ).In(
        Obj(
          "count", Var("count"),
          "total", Var("total"),
          "min", If(
                  LTE(Var("value"), Var("min")),
                  Var("value"),
                  Var("min")
          ),
          "max", If(
                  GTE(Var("value"), Var("max")),
                  Var("value"),
                  Var("max")
          ),
          "avg", Divide(Var("total"), Var("count"))
        )
      )
    ),
    Obj(
      "count", 0,
      "total", 0,
      "min", 999999,
      "max", -999999,
      "avg", 0
    ),
    Arr(1, 2, 3, 4, 5)
  )
);
result, err := client.Query(
  f.Reduce(
    f.Lambda(
      f.Arr{"acc", "value"},
      f.Let().Bind(
        "count", f.Add(f.Select("count", f.Var("acc")), 1)).Bind(
        "total", f.Add(f.Select("total", f.Var("acc")), f.Var("value"))).Bind(
        "min", f.Select("min", f.Var("acc"))).Bind(
        "max", f.Select("max", f.Var("acc"))).In(
        f.Obj{
          "count": f.Var("count"),
          "total": f.Var("total"),
          "min": f.If(
            f.LTE(f.Var("value"), f.Var("min")),
            f.Var("value"),
            f.Var("min")),
          "max": f.If(
            f.GTE(f.Var("value"), f.Var("max")),
            f.Var("value"),
            f.Var("max")),
          "avg": f.Divide(f.Var("total"), f.Var("count")),
        })),
    f.Obj{
      "count": 0,
      "total": 0,
      "min": 99999,
      "max": -99999,
      "avg": 0,
    },
    f.Arr{1, 2, 3, 4, 5}))
System.out.println(
    client.query(
        Reduce(
            Lambda(
                Arr(Value("acc"), Value("value")),
                Let(
                    "count", Add(Select(Path("count"), Var("acc")), Value(1))
                    "total", Add(Select(Path("total"), Var("acc")), Var("value"))
                    "min", Select(Path("min"), Var("acc"))
                    "max", Select(Path("max"), Var("acc"))
                ).in(
                    Obj(
                        "count", Var("count"),
                        "total", Var("total"),
                        "min", If(LTE(Var("value"), Var("min")), Var("value"), Var("min")),
                        "max", If(GTE(Var("value"), Var("max")), Var("value"), Var("max")),
                        "avg", Divide(Var("total"), Var("count"))
                    )
                )
            ),
            Obj(
              "count", Value(0),
              "total", Value(0),
              "min", Value(999999),
              "max", Value(-999999),
              "avg", Value(0),
            ),
            Arr( Value(1), Value(2), Value(3), Value(4), Value(5) )
        )
    ).get());
client.query(
  q.Reduce(
    q.Lambda((acc, value) => q.Let(
      {
        count: q.Add(q.Select('count', acc), 1),
        total: q.Add(q.Select('total', acc), value),
        min: q.Select('min', acc),
        max: q.Select('max', acc),
      },
      {
        count: q.Var('count'),
        total: q.Var('total'),
        min: q.If(q.LTE(value, q.Var('min')), value, q.Var('min')),
        max: q.If(q.GTE(value, q.Var('max')), value, q.Var('max')),
        avg: q.Divide(q.Var('total'), q.Var('count')),
      }
    )),
    {
      count: 0,
      total: 0,
      min: 999999,
      max: -999999,
      avg: 0,
    },
    [ 1, 2, 3, 4, 5 ]
  )
)
.then((ret) => console.log(ret))
print(client.query(
  q.reduce(
    q.lambda_(["acc", "value"], q.let(
      {
        "count": q.add(q.select("count", q.var("acc")), 1),
        "total": q.add(q.select("total", q.var("acc")), q.var("value")),
        "min": q.select("min", q.var("acc")),
        "max": q.select("max", q.var("acc")),
      },
      {
        "count": q.var("count"),
        "total": q.var("total"),
        "min": q.if_(
                q.lte(q.var("value"), q.var("min")),
                q.var("value"),
                q.var("min")
        ),
        "max": q.if_(
                q.gte(q.var("value"), q.var("max")),
                q.var("value"),
                q.var("max")
        ),
        "avg": q.divide(q.var("total"), q.var("count")),
      }
    )),
    {
      "count": 0,
      "total": 0,
      "min": 999999,
      "max": -999999,
      "avg": 0,
    },
    [ 1, 2, 3, 4, 5 ]
  )
))
Not available in this language yet.
println(Await.result(
  client.query(
    Reduce(
      Lambda {
        (acc, value) => Let {
          val count = Add(Select("count", acc), 1)
          val total = Add(Select("total", acc), value)
          val min   = Select("min", acc)
          val max   = Select("max", acc)
          Obj(
            "count" -> count,
            "total" -> total,
            "min"   -> If(LTE(value, min), value, min),
            "max"   -> If(GTE(value, max), value, max),
            "avg"   -> Divide(total, count)
          )
        }
      },
      Obj(
        "count" -> 0,
        "total" -> 0,
        "min"   -> 999999,
        "max"   -> -999999,
        "avg"   -> 0,
      ),
      Arr( 1, 2, 3, 4, 5 )
    )
  ),
  5.seconds
))
Not available in this language yet.
{
  "object": {
    "count": 5,
    "total": 15,
    "min": 1,
    "max": 5,
    "avg": 3
  }
}
map[avg:3 count:5 max:5 min:1 total:15]
{count: 5, avg: 3, min: 1, total: 15, max: 5}
{ count: 5, total: 15, min: 1, max: 5, avg: 3 }
{'count': 5, 'total': 15, 'min': 1, 'max': 5, 'avg': 3}
{count: 5, avg: 3, min: 1, total: 15, max: 5}

Was this article helpful?

We're sorry to hear that.
Tell us how we can improve! documentation@fauna.com

Thank you for your feedback!