---
title: "Function: simpleFlatten"
description: Flatten a document for integration with a non-NOSQL RDBMS.
pubDate: 2026-08-17T09:53:44.266Z
antora:
  editUrl: https://github.com/couchbaselabs/docs-devex/edit/release/8.0/modules/eventing/pages/eventing-handler-simpleFlatten.adoc
  xref: xref:server:eventing:eventing-handler-simpleFlatten.adoc[]
---

[Consult the llms.txt file for a full list of contents](/llms.txt)
[View original HTML](/server/current/eventing/eventing-handler-simpleFlatten.html)

# Function: simpleFlatten

**Goal**: Flatten a document for integration with a non-NOSQL RDBMS.

* This function **simpleFlatten** shows how a document can be flattened into a RDBMS importable record.
* Requires Eventing Storage (or metadata collection), a "source" collection, and a "destination" collection.
* Will operate on all documents where doc.type === "tosync".
* Will write transformed or flattened documents to the destination bucket with the same type and id.
* Will also remove the flattened document in the destination bucket when the original source document is removed.
* The "destination" collection can be shared (or replicated via XCDR to a business partner) too the cloud (AWS, Azure or GCP).
* Note since the document is not available during an OnDelete we will filter by KEY prefix starting with `"tosync:".*`. This is a hard coded implementation. Refer to [genericFlatten](eventing-handler-genericFlatten.md) for a generic implementation.

* simpleFlatten
* Input Data/Mutation
* Output Data/Mutation

```javascript
// To run configure the settings for this Function, simpleFlatten, as follows:
//
// Version 7.1+
//   "Function Scope"
//     *.* (or try bulk.data if non-privileged)
// Version 7.0+
//   "Listen to Location"
//     bulk.data.source
//   "Eventing Storage"
//     rr100.eventing.metadata
//   Binding(s)
//    1. "binding type", "alias name...", "bucket.scope.collection", "Access"
//       "bucket alias", "dst_col",       "bulk.data.destination",   "read and write"
//
// Version 6.X
//   "Source Bucket"
//     source
//   "MetaData Bucket"
//     metadata
//   Binding(s)
//    1. "binding type", "alias name...", "bucket",     "Access"
//       "bucket alias", "dst_col",      "destination", "read and write"

function OnUpdate(doc, meta) {
    // filter
    if (!doc.type || doc.type !== "tosync") return;

    log("OnUpdate IN  id: "+meta.id+", doc:      ",doc);
    try {
        // convert
        var oracleDoc = {
            // flatten items simple 1:1 map
            "id": doc.id, "type":doc.type,
            // flatten subdoc
            "a_sub_aa": doc.a.aa, "a_sub_ab": doc.a.ab,  "a_sub_ac": doc.a.ac,
            // flatten array
            "b_ary_0": doc.b[0], "b_ary_1": doc.b[1], "b_ary_2": doc.b[2]
        }
        // log
        log("OnUpdate OUT id: "+meta.id+", oracleDoc:",oracleDoc);
    } catch (e) {
        log ("Error on convert: "+e+", id:",meta.id);
    }
    // save
    try {
        dst_col[meta.id] = oracleDoc;
    } catch (e) {
        log("Error on save: "+e+", id:", meta.id);
    }
}

function OnDelete(meta, options) {
    // filter
    if (!(meta.id.startsWith("tosync:"))) return;

    log("OnDelete expired=" + options.expired +" REM id: "+meta.id);
    try {
        delete dst_col[meta.id];
    } catch (e) {
        log("Error on delete: "+e+", id:",meta.id);
    }
}
```

```json
INPUT: KEY tosync::1

{
  "id": 1,
  "type": "tosync",
  "a": {
    "aa": 1,
    "ab": 2,
    "ac": 3
  },
  "b": [
    1,
    3,
    7
  ]
}
```

```json
UPDATED/OUTPUT: KEY tosync::1

{
  "id": 1,
  "type": "tosync",
  "a_sub_aa": 1,
  "a_sub_ab": 2,
  "a_sub_ac": 3,
  "b_ary_0": 1,
  "b_ary_1": 3,
  "b_ary_2": 7
}
```