{"id":13533,"date":"2022-07-06T13:37:00","date_gmt":"2022-07-06T20:37:00","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=13533"},"modified":"2025-06-13T22:40:18","modified_gmt":"2025-06-14T05:40:18","slug":"eventing-data-consolidation-in-couchbase","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/","title":{"rendered":"Using the Eventing Service to Consolidate Data from Multiple Sources"},"content":{"rendered":"<p><span style=\"font-weight: 400\">One of the many advantages of using a document-based database such as Couchbase is the ability to use a flexible data model to store data without the constraints of a rigid, predetermined schema. Many customers choose a NoSQL database to support the ingestion of data from multiple sources. But what if you need your data transformed so that it matches your existing data? Maybe you need it all in a uniform format for reporting purposes. Whatever the reason, this is a perfect use for the <a href=\"https:\/\/www.couchbase.com\/products\/eventing\/\">Eventing Service<\/a> in Couchbase.<\/span><\/p>\n<h2>Couchbase Eventing Service<\/h2>\n<p><span style=\"font-weight: 400\">The eventing service is a built-in feature of Couchbase Enterprise Edition that allows the application of JavaScript functions, <\/span><span style=\"font-weight: 400\">or <em>lambdas<\/em><\/span><span style=\"font-weight: 400\">, that respond to mutation events. Whenever a document is created, modified, or deleted, an action can be taken <\/span><span style=\"font-weight: 400\">by <em>executing pure business logic in your JavaScript<\/em><\/span><span style=\"font-weight: 400\">. There are a number of actions that can be taken, such as data enrichment, calling of external workflows (via RESTful API calls), and timer-based events (resuming execution in the future). Think of events as a legacy database <\/span><span style=\"font-weight: 400\">post-<\/span><span style=\"font-weight: 400\">trigger on steroids.<\/span><\/p>\n<h2>Data consolidation<\/h2>\n<p><span style=\"font-weight: 400\">In this simplified example, imagine you have just acquired two new data sources for customer data. This data might be coming from a normalized source, or in a flat file, or both, and you want this data to match your existing customer data stored in a denormalized format.<\/span><\/p>\n<p><span style=\"font-weight: 400\">The first data source is a normalized database (<\/span><span style=\"font-weight: 400\">clean and accurate) <\/span><span style=\"font-weight: 400\">containing customers in Canada. Each customer record points to a billing and a shipping address, and each address is normalized to eliminate redundancy of city and province data:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13534\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image6-1024x552.png\" alt=\"Normalized datasource for eventing\" width=\"900\" height=\"485\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image6-1024x552.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image6-300x162.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image6-768x414.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image6-20x11.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image6.png 1084w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><br \/>\n<span style=\"font-weight: 400\">The second data source is a flat file also containing Canadian customers, but that does not track separate billing and shipping addresses. As you can see, <\/span><span style=\"font-weight: 400\">only a single address data element<\/span><span style=\"font-weight: 400\"> is stored within the customer record:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13535\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image10.png\" alt=\"Customer table, data model of single address data\" width=\"462\" height=\"600\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image10.png 462w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image10-231x300.png 231w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image10-300x390.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image10-15x20.png 15w\" sizes=\"auto, (max-width: 462px) 100vw, 462px\" \/><\/p>\n<p><span style=\"font-weight: 400\">We need to transform this data as it comes in so that it matches our existing customer database which is denormalized such that billing and shipping addresses are attached to the customer data (<\/span><span style=\"font-weight: 400\">from the second source<\/span><span style=\"font-weight: 400\">) as sub-documents:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13536\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image7-1024x238.png\" alt=\"Creating sub-documents on denormalzied data model\" width=\"900\" height=\"209\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-1024x238.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-300x70.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-768x178.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-1536x357.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-20x5.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7-1320x307.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image7.png 1636w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Let\u2019s start with <\/span><span style=\"font-weight: 400\">an easy<\/span><span style=\"font-weight: 400\"> solution first, the flat file import. The process for transforming this data involves copying the customer data (name, email, phone, company name) into a new document. The address data then needs to be copied into subdocuments for both billing and mailing addresses. Because we only have one address per customer, we\u2019ll copy this address into both the billing and the mailing address subdocument:<\/span><\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13537\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image5-1024x706.png\" alt=\"Importing and transforming subdocuments\" width=\"900\" height=\"621\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-1024x706.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-300x207.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-768x530.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-1536x1059.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-20x14.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5-1320x910.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image5.png 1636w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><br \/>\n<span style=\"font-weight: 400\">JavaScript code to consolidate the tables<\/span><\/h2>\n<p><span style=\"font-weight: 400\">The Eventing code to accomplish this is quite simple:<\/span><\/p>\n<pre class=\"nums:false nums-toggle:false decode-attributes:false lang:js decode:true\"> \u00a01 function OnUpdate(doc, meta) {\r\n\u00a0\u00a02 \u00a0 \u00a0 const new_doc = {}; \/\/ New customer document\r\n\u00a0\u00a03 \u00a0 \u00a0 const address = {}; \/\/ New address document\r\n\u00a0\u00a04\r\n\u00a0\u00a05 \u00a0 \u00a0 new_doc['first_name'] = doc.first_name;\r\n\u00a0\u00a06 \u00a0 \u00a0 new_doc['last_name'] = doc.last_name;\r\n\u00a0\u00a07 \u00a0 \u00a0 new_doc['email'] = doc.email;\r\n\u00a0\u00a08 \u00a0 \u00a0 new_doc['phone'] = doc.phone;\r\n\u00a0\u00a09 \u00a0 \u00a0 new_doc['company_name'] = doc.company_name;\r\n\u00a010\r\n\u00a011 \u00a0 \u00a0 address['street_address_1'] = doc.street_address_1;\r\n\u00a012 \u00a0 \u00a0 address['street_address_2'] = doc.street_address_2;\r\n\u00a013 \u00a0 \u00a0 address['city'] = doc.city;\r\n\u00a014 \u00a0 \u00a0 address['state'] = doc.province;\r\n\u00a015 \u00a0 \u00a0 address['zip_code'] = doc.postal_code;\r\n\u00a016\r\n\u00a017 \u00a0 \u00a0 \/\/ Add address document to customer document as subdocuments\r\n\u00a018 \u00a0 \u00a0 new_doc['billing_address'] = address;\r\n\u00a019 \u00a0 \u00a0 new_doc['mailing_address'] = address;\r\n\u00a020\r\n\u00a021 \u00a0 \u00a0 \/\/ This creates the new document in the destination bucket\r\n\u00a022 \u00a0 \u00a0 dest_bkt[doc.email] = new_doc;\r\n\u00a023\r\n\u00a024 \u00a0 \u00a0 \/\/ Delete original document - uncomment below\r\n\u00a025 \u00a0 \u00a0 \/\/ delete sch2[meta.id];\r\n\u00a026\r\n\u00a027 \u00a0 \u00a0 log(\"Doc created\/updated\", meta.id);\r\n\u00a028 }<\/pre>\n<p><span style=\"font-weight: 400\">The above code should be easy enough to understand, even for non JavaScript coders, but I\u2019ll break this down by section just to be sure.<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li><span style=\"font-weight: 400\"><em>Line 1<\/em> above is called anytime a document in the source bucket is mutated (created or modified). We\u2019ll see below how we define the source bucket.<\/span><\/li>\n<li><span style=\"font-weight: 400\">Lines 2-3 create JavaScript objects to hold the new customer document and the address document that will be used as subdocuments within the customer document.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 5-15<\/em> copy the properties from the original document into the customer and address objects.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 18 and 19<\/em> assign the address document as customer subdocuments for both mailing and billing address properties.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Line 22<\/em> actually creates the document in the Couchbase destination bucket. We\u2019ll see below how we define the destination bucket.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Finally line 25<\/em> will delete the original document, although it\u2019s commented out here.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Line 27<\/em> logs the operation. You may want to comment\/remove this after testing.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Set up environment<\/h2>\n<p><span style=\"font-weight: 400\">To test this script, we\u2019ll need to set up our Couchbase environment. First of all, we\u2019ll need a Couchbase cluster running the data service as well as the eventing service. This can be as small as a single node cluster running in Docker, or a larger multi-node cluster running in Capella.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Once we have the cluster up and running, we\u2019ll need to create the buckets for importing data, and a final destination bucket. The eventing service also requires a metadata bucket. Create the following four buckets, each with the minimum required quota of 100mb:<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li style=\"font-weight: 400\"><em><span style=\"font-weight: 400\">schema1<\/span><\/em><\/li>\n<li style=\"font-weight: 400\"><em><span style=\"font-weight: 400\">schema2<\/span><\/em><\/li>\n<li style=\"font-weight: 400\"><em><span style=\"font-weight: 400\">customer<\/span><\/em><\/li>\n<li style=\"font-weight: 400\"><em><span style=\"font-weight: 400\">eventing_merge\u00a0<\/span><\/em><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">I also recommend enabling <em>flush<\/em> for this exercise.<\/span><\/p>\n<h3>Creating an eventing function<\/h3>\n<p><span style=\"font-weight: 400\">Now we need to create the eventing function. Select the <strong>eventing<\/strong> tab, and then click <strong>Add Function<\/strong>. Use the following settings:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13538\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image3-727x1024.png\" alt=\"Eventing function settings in Couchbase\" width=\"727\" height=\"1024\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-727x1024.png 727w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-213x300.png 213w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-768x1082.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-1090x1536.png 1090w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-300x423.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3-14x20.png 14w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image3.png 1280w\" sizes=\"auto, (max-width: 727px) 100vw, 727px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Next click on <strong>Next: Add Code<\/strong>\u00a0and replace the default <em>OnUpdate<\/em> function with the code from above. Click <strong>Save<\/strong> <strong>and Return<\/strong>. At this point the code has been stored, but the function needs to be deployed in order for it to begin processing data. Click on the function name to open up its settings and go ahead and deploy the function now.<\/span><\/p>\n<h3>Creating test JSON documents<\/h3>\n<p><span style=\"font-weight: 400\">Now let\u2019s test it by creating a document in the <em>schema2<\/em> bucket. Add a document using <\/span><em><span style=\"font-weight: 400\">wile.e.coyote@acmecorp.com<\/span><\/em><span style=\"font-weight: 400\">\u00a0as the document key, and with the following document body:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"customer_id\": null,\r\n\u00a0\u00a0\"first_name\": \"Wile\",\r\n\u00a0\u00a0\"middle_name\": \"E\",\r\n\u00a0\u00a0\"last_name\": \"Coyote\",\r\n\u00a0\u00a0\"email\": \"wile.e.coyote@acmecorp.com\",\r\n\u00a0\u00a0\"title\": \"Genius\",\r\n\u00a0\u00a0\"company_name\": \"Acme Corporation\",\r\n\u00a0\u00a0\"phone\": \"123-555-1212\",\r\n\u00a0\u00a0\"street_address_1\": \"694 York Circle\",\r\n\u00a0\u00a0\"street_address_2\": \"\",\r\n\u00a0\u00a0\"city\": \"Hackettstown\",\r\n\u00a0\u00a0\"province\": \"NJ\",\r\n\u00a0\u00a0\"postal_code\": \"07840\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\">In just a moment, you should see the statistics for the event indicate success:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13539\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image2.png\" alt=\"event status feedback\" width=\"850\" height=\"274\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image2.png 850w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image2-300x97.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image2-768x248.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image2-20x6.png 20w\" sizes=\"auto, (max-width: 850px) 100vw, 850px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Now look in the <em>customer<\/em> bucket, and you should see the document above has been transformed. Notice how the address now exists as subdocuments within the properties <em>billing_address<\/em>\u00a0and <em>mailing_address<\/em>:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13540\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image11.png\" alt=\"sampel JSON document for addresses\" width=\"740\" height=\"778\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image11.png 740w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image11-285x300.png 285w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image11-300x315.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image11-20x20.png 20w\" sizes=\"auto, (max-width: 740px) 100vw, 740px\" \/><\/p>\n<h2>Transforming to sub-documents<\/h2>\n<p><span style=\"font-weight: 400\">Now let\u2019s tackle the more complex schema transformation. Migrating the relational structure to match our sub-document structure looks something like this:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13541\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image1-1024x727.png\" alt=\"Migrating the relational structure to match our sub-document structure\" width=\"900\" height=\"639\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-1024x727.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-300x213.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-768x545.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-1536x1090.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-20x14.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1-1320x937.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image1.png 1730w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><br \/>\n<span style=\"font-weight: 400\">We\u2019ll need to denormalize the address and postal code tables into a single subdocument, one each for the shipping\/mailing and billing addresses. In this case, the data from the three tables is stored in collections within the bucket.\u00a0<\/span><\/p>\n<h2><span style=\"font-weight: 400\">JavaScript code for denormalization<\/span><\/h2>\n<pre class=\"nums:false nums-toggle:false decode-attributes:false lang:js decode:true\"> \u00a01 function OnUpdate(doc, meta) {\r\n\u00a0\u00a02 \u00a0 \u00a0 let new_doc = {};\r\n\u00a0\u00a03 \u00a0 \u00a0 let bill_addr = {};\r\n\u00a0\u00a04 \u00a0 \u00a0 let mail_addr = {};\r\n\u00a0\u00a05\r\n\u00a0\u00a06 \u00a0 \u00a0 new_doc['first_name'] = doc.first_name;\r\n\u00a0\u00a07 \u00a0 \u00a0 new_doc['last_name'] = doc.last_name;\r\n\u00a0\u00a08 \u00a0 \u00a0 new_doc['email'] = doc.email;\r\n\u00a0\u00a09 \u00a0 \u00a0 new_doc['phone'] = doc.phone;\r\n\u00a010 \u00a0 \u00a0 new_doc['company_name'] = doc.company_name;\r\n\u00a011\r\n\u00a012 \u00a0 \u00a0 bill_addr = bkt_addr[doc.billing_address_id];\r\n\u00a013 \u00a0 \u00a0 mail_addr = bkt_addr[doc.shipping_address_id];\r\n\u00a014\r\n\u00a015 \u00a0 \u00a0 bill_addr['city'] = bkt_pc[bkt_addr[doc.billing_address_id].postal_code].city;\r\n\u00a016 \u00a0 \u00a0 mail_addr['city'] = bkt_pc[bkt_addr[doc.shipping_address_id].postal_code].city;\r\n\u00a017\r\n\u00a018 \u00a0 \u00a0 bill_addr['state'] = bkt_pc[bkt_addr[doc.billing_address_id].postal_code].province;\r\n\u00a019 \u00a0 \u00a0 mail_addr['state'] = bkt_pc[bkt_addr[doc.shipping_address_id].postal_code].province;\r\n\u00a020\r\n\u00a021 \u00a0 \u00a0 new_doc['billing_address'] = bill_addr;\r\n\u00a022 \u00a0 \u00a0 new_doc['mailing_address'] = mail_addr;\r\n\u00a023\r\n\u00a024 \u00a0 \u00a0 log(new_doc);\r\n\u00a025\r\n\u00a026 \u00a0 \u00a0 dest_bkt[doc.email] = new_doc;\r\n\u00a027\r\n\u00a028 \u00a0 \u00a0 \/\/ Delete existing customer (leave address\/postal_code for other customers who share this)\r\n\u00a029 \u00a0 \u00a0 \/\/ delete bkt_cust[meta.id];\r\n\u00a030 \u00a0 \u00a0 log(\"Doc created\/updated\", meta.id);\r\n\u00a031 }<\/pre>\n<p><span style=\"font-weight: 400\">We\u2019ll break down this code again as before.<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li><span style=\"font-weight: 400\"><em>Lines 2-4<\/em> create JavaScript Objects to store the new document as well as the subdocuments for the mailing and billing addresses.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 6-10<\/em> copy the contact properties to the new document.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 12 and 13<\/em> copy the address data from the address collection using the document key stored in the contact address_id property.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 15-19<\/em> pull the city and province data out of the province collection, using the province_id from the address document as the document key.<\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Lines 21 and 22<\/em> then attach these document objects as subdocuments to the new contact document.<\/span><\/li>\n<li><span style=\"font-weight: 400\">Finally, <em>line 26<\/em> writes the new document to the destination bucket. <\/span><\/li>\n<li><span style=\"font-weight: 400\"><em>Line 29<\/em>, if uncommented, will delete the original contact document from the source bucket. Note that we do not want to also delete the associated address and province documents because they may be used by other contacts.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Creating the eventing function for denormalization<\/h2>\n<p><span style=\"font-weight: 400\">Create this eventing function using the following settings, and paste the above code in to replace the <em>OnUpdate<\/em> function. When finished, go ahead and deploy the function.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13542\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image4-556x1024.png\" alt=\"Setting up an eventing function in Couchbase\" width=\"556\" height=\"1024\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-556x1024.png 556w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-163x300.png 163w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-768x1414.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-834x1536.png 834w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-300x552.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4-11x20.png 11w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image4.png 1086w\" sizes=\"auto, (max-width: 556px) 100vw, 556px\" \/><\/p>\n<p><span style=\"font-weight: 400\">To test this function, we\u2019ll need to create collections in the <em>schema1<\/em> bucket (use the <em>default<\/em> scope) with the names: <em>addresses<\/em>, <em>customers<\/em>, <em>postal_codes<\/em>. Then create the following documents (in this order, otherwise the lookups in the function will fail):<\/span><\/p>\n<p><span style=\"font-weight: 400\"><em>Postal_codes<\/em> collection, with document ID <\/span><span style=\"font-weight: 400\"><em>43062<\/em>:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"postal_code\": \"43062\",\r\n\u00a0\u00a0\"city\": \"Pataskala\",\r\n\u00a0\u00a0\"province\": \"OH\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\"><em>Postal_codes<\/em> collection, with document ID <\/span><span style=\"font-weight: 400\"><em>23228<\/em>:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"postal_code\": \"23228\",\r\n\u00a0\u00a0\"city\": \"Henrico\",\r\n\u00a0\u00a0\"province\": \"VA\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\"><em>Addresses<\/em> collection, with document ID <em>000071<\/em>:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"address_id\": \"000071\",\r\n\u00a0\u00a0\"street_address_1\": \"85 Hartford Road\",\r\n\u00a0\u00a0\"street_address_2\": \"\",\r\n\u00a0\u00a0\"postal_code\": \"23228\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\"><em>Addresses<\/em> collection, with document ID <em>000086<\/em>:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"address_id\": \"000086\",\r\n\u00a0\u00a0\"street_address_1\": \"460 Broad Dr.\",\r\n\u00a0\u00a0\"street_address_2\": \"\",\r\n\u00a0\u00a0\"postal_code\": \"43062\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\">Finally, in the <em>customers<\/em> collection, with document ID <\/span><em><span style=\"font-weight: 400\">blinded_by@science.com<\/span><\/em><span style=\"font-weight: 400\">:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">{\r\n\u00a0\u00a0\"customer_id\": null,\r\n\u00a0\u00a0\"first_name\": \"Thomas\",\r\n\u00a0\u00a0\"middle_name\": null,\r\n\u00a0\u00a0\"last_name\": \"Dolby\",\r\n\u00a0\u00a0\"email\": \"blinded_by@science.com\",\r\n\u00a0\u00a0\"title\": null,\r\n\u00a0\u00a0\"phone\": \"867-5309\",\r\n\u00a0\u00a0\"billing_address_id\": \"000086\",\r\n\u00a0\u00a0\"shipping_address_id\": \"000071\",\r\n\u00a0\u00a0\"company_name\": \"The Golden Age of Wireless\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400\">Fairly quickly you should see the statistics for this function show success:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13543\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image8.png\" alt=\"Function success status\" width=\"764\" height=\"244\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image8.png 764w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image8-300x96.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image8-20x6.png 20w\" sizes=\"auto, (max-width: 764px) 100vw, 764px\" \/><\/p>\n<p><span style=\"font-weight: 400\">And if you look at the document in the customers bucket, you should see the following transformation with the two addresses denormalized into subdocuments.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13544\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/07\/image9.png\" alt=\"Automatic denormalization of JSON documents using eventing\" width=\"672\" height=\"734\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image9.png 672w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image9-275x300.png 275w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image9-300x328.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image9-18x20.png 18w\" sizes=\"auto, (max-width: 672px) 100vw, 672px\" \/><\/p>\n<h2>Closing thoughts<\/h2>\n<p><span style=\"font-weight: 400\">This is a very simplistic example. In a production environment, you\u2019ll likely add code to handle exceptions.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Also you may increase the number of workers from 1 to the number of vCPUs if you have a large dataset and require greater performance<\/span><span style=\"font-weight: 400\">.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">The eventing functions used in this blog can be found in the following github repo: <\/span><a href=\"https:\/\/github.com\/djames42\/cb_eventing_merge\"><span style=\"font-weight: 400\">https:\/\/github.com\/djames42\/cb_eventing_merge<\/span><\/a><span style=\"font-weight: 400\">. In this repository are also a couple of scripts (both a Bash script and a Python script) that can be used to build out a single node cluster with the eventing functions and larger sample datasets pre-loaded.<\/span><\/p>\n<h2>Resources<\/h2>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li style=\"font-weight: 400\"><i><span style=\"font-weight: 400\">Download:<\/span><\/i><a href=\"https:\/\/couchbase.com\/downloads\/?ref=blog\"><span style=\"font-weight: 400\"> Download Couchbase Server 7.1<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><i><span style=\"font-weight: 400\">GitHub:<\/span><\/i> <a href=\"https:\/\/github.com\/djames42\/cb_eventing_merge\"><span style=\"font-weight: 400\">https:\/\/github.com\/djames42\/cb_eventing_merge<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>References<\/h2>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/server\/6.6\/eventing\/eventing-overview.html?ref=blog\"><span style=\"font-weight: 400\">Couchbase Eventing documentation<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/www.couchbase.com\/blog\/whats-new-in-couchbase-server-7-1\/\"><span style=\"font-weight: 400\">What&#8217;s New: Couchbase Server 7.1<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/www.couchbase.com\/blog\/tag\/eventing\/?ref=blog\"><span style=\"font-weight: 400\">Other Couchbase blogs on Eventing<\/span><\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the many advantages of using a document-based database such as Couchbase is the ability to use a flexible data model to store data without the constraints of a rigid, predetermined schema. Many customers choose a NoSQL database to [&hellip;]<\/p>\n","protected":false},"author":69851,"featured_media":13547,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,2273,9327],"tags":[2226,1447,1450,2100],"ppma_author":[9688],"class_list":["post-13533","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-eventing","category-javascript","tag-couchbase-functions","tag-data-modeling","tag-document-normalization","tag-lambda"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using the Eventing Service to Consolidate Data from Multiple Sources<\/title>\n<meta name=\"description\" content=\"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using the Eventing Service to Consolidate Data from Multiple Sources\" \/>\n<meta property=\"og:description\" content=\"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-06T20:37:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T05:40:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2163\" \/>\n\t<meta property=\"og:image:height\" content=\"1535\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Daniel James, Senior Solutions Engineer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel James, Senior Solutions Engineer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\"},\"author\":{\"name\":\"DanielJames\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/be62ea90bcc04b8ec2df1755e6e186d7\"},\"headline\":\"Using the Eventing Service to Consolidate Data from Multiple Sources\",\"datePublished\":\"2022-07-06T20:37:00+00:00\",\"dateModified\":\"2025-06-14T05:40:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\"},\"wordCount\":1366,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png\",\"keywords\":[\"Couchbase Functions\",\"Data Modeling\",\"Document Normalization\",\"lambda\"],\"articleSection\":[\"Couchbase Server\",\"Eventing\",\"JavaScript\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\",\"name\":\"Using the Eventing Service to Consolidate Data from Multiple Sources\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png\",\"datePublished\":\"2022-07-06T20:37:00+00:00\",\"dateModified\":\"2025-06-14T05:40:18+00:00\",\"description\":\"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png\",\"width\":2163,\"height\":1535},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using the Eventing Service to Consolidate Data from Multiple Sources\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/be62ea90bcc04b8ec2df1755e6e186d7\",\"name\":\"DanielJames\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/1808e27bf0c87c8e9f636c9636d84c88\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f467ae6133e0e29b659987b13b695261d798c1763f401e09631151e72bcb73b3?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f467ae6133e0e29b659987b13b695261d798c1763f401e09631151e72bcb73b3?s=96&d=mm&r=g\",\"caption\":\"DanielJames\"},\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/danieljames\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using the Eventing Service to Consolidate Data from Multiple Sources","description":"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/","og_locale":"en_US","og_type":"article","og_title":"Using the Eventing Service to Consolidate Data from Multiple Sources","og_description":"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.","og_url":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/","og_site_name":"The Couchbase Blog","article_published_time":"2022-07-06T20:37:00+00:00","article_modified_time":"2025-06-14T05:40:18+00:00","og_image":[{"width":2163,"height":1535,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png","type":"image\/png"}],"author":"Daniel James, Senior Solutions Engineer","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Daniel James, Senior Solutions Engineer","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/"},"author":{"name":"DanielJames","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/be62ea90bcc04b8ec2df1755e6e186d7"},"headline":"Using the Eventing Service to Consolidate Data from Multiple Sources","datePublished":"2022-07-06T20:37:00+00:00","dateModified":"2025-06-14T05:40:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/"},"wordCount":1366,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png","keywords":["Couchbase Functions","Data Modeling","Document Normalization","lambda"],"articleSection":["Couchbase Server","Eventing","JavaScript"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/","url":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/","name":"Using the Eventing Service to Consolidate Data from Multiple Sources","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png","datePublished":"2022-07-06T20:37:00+00:00","dateModified":"2025-06-14T05:40:18+00:00","description":"Couchbase eventing functions can be used to help consolidate data from differing sources\/data models, here we denormalize tables on the fly.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/07\/image_2022-07-06_133336281.png","width":2163,"height":1535},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/eventing-data-consolidation-in-couchbase\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using the Eventing Service to Consolidate Data from Multiple Sources"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/be62ea90bcc04b8ec2df1755e6e186d7","name":"DanielJames","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/1808e27bf0c87c8e9f636c9636d84c88","url":"https:\/\/secure.gravatar.com\/avatar\/f467ae6133e0e29b659987b13b695261d798c1763f401e09631151e72bcb73b3?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f467ae6133e0e29b659987b13b695261d798c1763f401e09631151e72bcb73b3?s=96&d=mm&r=g","caption":"DanielJames"},"url":"https:\/\/www.couchbase.com\/blog\/author\/danieljames\/"}]}},"authors":[{"term_id":9688,"user_id":69851,"is_guest":0,"slug":"danieljames","display_name":"Daniel James, Senior Solutions Engineer","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f467ae6133e0e29b659987b13b695261d798c1763f401e09631151e72bcb73b3?s=96&d=mm&r=g","author_category":"","last_name":"James","first_name":"Daniel","job_title":"","user_url":"","description":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13533","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/69851"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=13533"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13533\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13547"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=13533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=13533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=13533"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=13533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}