{"id":26052739,"url":"https://github.com/robtweed/ewd-document-store-examples","last_synced_at":"2026-04-17T13:32:25.859Z","repository":{"id":66165301,"uuid":"102114211","full_name":"robtweed/ewd-document-store-examples","owner":"robtweed","description":"ewd-document-store module examples","archived":false,"fork":false,"pushed_at":"2017-10-26T16:38:41.000Z","size":12,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-31T07:32:06.585Z","etag":null,"topics":["ewd-document-store","examples","express","intersystems-cache"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robtweed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-01T13:12:29.000Z","updated_at":"2020-05-25T14:49:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"f291546b-238e-4893-ad0a-239018228762","html_url":"https://github.com/robtweed/ewd-document-store-examples","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/robtweed/ewd-document-store-examples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtweed%2Fewd-document-store-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtweed%2Fewd-document-store-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtweed%2Fewd-document-store-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtweed%2Fewd-document-store-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robtweed","download_url":"https://codeload.github.com/robtweed/ewd-document-store-examples/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtweed%2Fewd-document-store-examples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31931334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-17T12:37:54.787Z","status":"ssl_error","status_checked_at":"2026-04-17T12:37:25.095Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ewd-document-store","examples","express","intersystems-cache"],"created_at":"2025-03-08T06:42:05.114Z","updated_at":"2026-04-17T13:32:25.853Z","avatar_url":"https://github.com/robtweed.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# ewd-document-store-examples\n\nRob Tweed \u003crtweed@mgateway.com\u003e  \n7 September 2017, M/Gateway Developments Ltd [http://www.mgateway.com](http://www.mgateway.com)  \n\nTwitter: [@rtweed](https://twitter.com/rtweed)\n\nGoogle Group for discussions, support, advice etc: [http://groups.google.co.uk/group/enterprise-web-developer-community](http://groups.google.co.uk/group/enterprise-web-developer-community)\n\n© 2017 M/Gateway Developments Ltd\n\n\n# Table of Contents\n  \n  - [InterSystem Caché](#toe-intersystem-cache)\n  - [Caché Standalone Examples](#toe-cache-standalone-examples)\n    * [Creating Document Nodes](#toe-creating-document-nodes)\n    * [Updating Document Nodes](#toe-updating-document-nodes)\n    * [For Each Methods](#toe-foreach-methods)\n      * [forEachChild](#toe-foreachchild)\n      * [forEachLeafNode](#toe-foreachleafnode)\n    * [Traversing Document Nodes](#toe-traversing-document-nodes)\n      * [countChildren()](#toe-traversing-countChildren)\n      * [$()](#toe-traversing-$)\n      * [parent](#toe-traversing-parent)\n      * [firstChild / nextSibling](#toe-traversing-firstChild-nextSibling)\n      * [value](#toe-traversing-value)\n      * [delete()](#toe-traversing-delete)\n    * [Gets a List of Globals](#toe-gets-list-of-globals)\n  * [Caché Worker Module Example and Express Integration using ewd-qoper8-express](#toe-worker-module-example-and-express-integration-using-ewd-qoper-express)\n    * [Using WebSockets](#toe-using-websockets)\n\n------\n\n## \u003ca id=\"toe-cache\"\u003e\u003c/a\u003eInterSystem Caché\n\n  - [Documentation Home Page](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.HomePageZen.cls)\n  - [Caché Installation Guide](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCI)\n  - [Using Node.js with Caché](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=BXJS)\n\n\n## \u003ca id=\"toe-cache-standalone-examples\"\u003e\u003c/a\u003eCaché Standalone Examples\n\nHere's standalone example of ewd-document-store working with [InterSystem Caché](http://www.intersystems.com/our-products/cache/cache-overview/). You'll find this in the /examples directory - look for CacheStandalone.js:\n\n```js\n'use strict';\n\n// Standalone example demonstrating use of ewd-document-store with Cache database\n// You may need to run this as sudo because of permissions\nvar DocumentStore = require('ewd-document-store');\nvar Cache = require('cache').Cache;\nvar db = new Cache();\n\n// Change these parameters to match your GlobalsDB or Cache system:\nvar ok = db.open({\n  path: '/opt/cache/mgr',\n  username: '_SYSTEM',\n  password: 'SYS',\n  namespace: 'USER'\n});\n\nconsole.log('ok: ' + JSON.stringify(ok));\nconsole.log('version: ' + db.version());\n```\n\nIf things are correct, you should get a response back such as this:\n```\nok: {\"ok\":1,\"result\":1,\"cache_pid\":\"86289\"}\nversion: Node.js Adaptor for Cache: Version: 1.1.140 (CM); Cache Version: 2017.1 build 111\n```\n\n### \u003ca id=\"toe-creating-document-nodes\"\u003e\u003c/a\u003eCreating Document Nodes\n\nNext, initializing document store and creating a couple document nodes:\n```js\nvar documentStore = new DocumentStore(db);\nvar rob = new documentStore.DocumentNode('rob');\n\nvar temp = new documentStore.DocumentNode('temp', [1]);\nconsole.log('exists: ' + temp.exists);\nconsole.log('hasValue: ' + temp.hasValue);\nconsole.log('hasChildren: ' + temp.hasChildren);\nconsole.log('value: ' + temp.value);\n\nconsole.log(JSON.stringify(temp.getDocument(), null, 2));\n```\nResponse:\n```\nexists: false\nhasValue: false\nhasChildren: false\nvalue:\n{}\n```\n\n### \u003ca id=\"toe-updating-document-nodes\"\u003e\u003c/a\u003eUpdating Document Nodes\n\nLet's add event listener on `afterSet` event and set some values using `$` and `increment` methods:\n```js\ndocumentStore.on('afterSet', function (node) {\n  console.log('afterSet: ' + JSON.stringify(node));\n});\nrob.$('x').value = 'hello';\nrob.$('y').value = 'world';\nrob.$('a').increment();\n```\nResponse:\n```\nafterSet: {\"documentName\":\"rob\",\"path\":[\"x\"],\"before\":{\"value\":\"hello\",\"exists\":true},\"value\":\"hello\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"y\"],\"before\":{\"value\":\"world\",\"exists\":true},\"value\":\"world\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"a\"],\"before\":{\"value\":\"1\",\"exists\":true},\"value\":\"3\"}\n```\n\nLet's declare a variable and use `setDocument` method to replace the whole document:\n```js\nvar z = {\n  a: 'this is a',\n  b: 'this is b',\n  Barton: 'J',\n  Briggs: 'A',\n  Davies: 'D',\n  Davis: 'T',\n  Douglas: 'N',\n  c: ['a', 's', 'd'],\n  d: {\n    a: 'a',\n    b: 'b'\n  }\n};\n\nrob.$('z').setDocument(z);\n\nconsole.log(JSON.stringify(rob.getDocument(), null, 2));\n```\nResponse:\n```\nafterSet: {\"documentName\":\"rob\",\"path\":[\"x\"],\"before\":{\"value\":\"hello\",\"exists\":true},\"value\":\"hello\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"y\"],\"before\":{\"value\":\"world\",\"exists\":true},\"value\":\"world\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"a\"],\"before\":{\"value\":\"1\",\"exists\":true},\"value\":\"5\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"a\"],\"before\":{\"value\":\"this is a\",\"exists\":true},\"value\":\"this is a\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"b\"],\"before\":{\"value\":\"this is b\",\"exists\":true},\"value\":\"this is b\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"Barton\"],\"before\":{\"value\":\"J\",\"exists\":true},\"value\":\"J\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"Briggs\"],\"before\":{\"value\":\"A\",\"exists\":true},\"value\":\"A\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"Davies\"],\"before\":{\"value\":\"D\",\"exists\":true},\"value\":\"D\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"Davis\"],\"before\":{\"value\":\"T\",\"exists\":true},\"value\":\"T\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"Douglas\"],\"before\":{\"value\":\"N\",\"exists\":true},\"value\":\"N\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"c\",0],\"before\":{\"value\":\"a\",\"exists\":true},\"value\":\"a\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"c\",1],\"before\":{\"value\":\"s\",\"exists\":true},\"value\":\"s\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"c\",2],\"before\":{\"value\":\"d\",\"exists\":true},\"value\":\"d\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"d\",\"a\"],\"before\":{\"value\":\"a\",\"exists\":true},\"value\":\"a\"}\nafterSet: {\"documentName\":\"rob\",\"path\":[\"z\",\"d\",\"b\"],\"before\":{\"value\":\"b\",\"exists\":true},\"value\":\"b\"}\n{\n  \"a\": \"1\",\n  \"x\": \"hello\",\n  \"y\": \"world\",\n  \"z\": {\n    \"Barton\": \"J\",\n    \"Briggs\": \"A\",\n    \"Davies\": \"D\",\n    \"Davis\": \"T\",\n    \"Douglas\": \"N\",\n    \"a\": \"this is a\",\n    \"b\": \"this is b\",\n    \"c\": {\n      \"0\": \"a\",\n      \"1\": \"s\",\n      \"2\": \"d\"\n    },\n    \"d\": {\n      \"a\": \"a\",\n      \"b\": \"b\"\n    }\n  }\n}\n```\n\n### \u003ca id=\"toe-foreach-methods\"\u003e\u003c/a\u003e For Each Methods\n\n#### \u003ca id=\"toe-foreachchild\"\u003e\u003c/a\u003e forEachChild\n\nLet's go through each child in rob document:\n```js\nconsole.log('forEachChild through rob document:');\nrob.forEachChild(function (nodeName) {\n  console.log(nodeName);\n});\n```\nResponse:\n```\nforEachChild through rob document:\na\nx\ny\nz\n```\n\nLet's go through each child in rob document but stopping early:\n```js\nconsole.log('forEachChild through rob document, stopping early:');\nrob.forEachChild(function (nodeName) {\n  console.log(nodeName);\n  if (nodeName === 'x') {\n    return true;\n  }\n});\n```\nResponse:\n```\nforEachChild through rob document, stopping early:\na\nx\n```\n\nLet's go through each child in rob document in reverse:\n```js\nconsole.log('forEachChild through rob document, in reverse:');\nrob.forEachChild({\n  direction: 'reverse'\n}, function (nodeName) {\n  console.log(nodeName);\n});\n```\nResponse:\n```\nforEachChild through rob document, in reverse:\nz\ny\nx\na\n```\n\nLet's go through each child in rob document starting with:\n```js\nconsole.log('forPrefix through rob global starting x:');\nrob.forEachChild({\n  prefix: 'x'\n}, function (subscript) {\n  console.log(subscript);\n});\n```\nResponse:\n```\nforPrefix through rob global starting x:\nx\n```\n\nLet's use range option property to filter child nodes:\n```js\nvar z = rob.$z;\nconsole.log('Names from Br to Da');\nz.forEachChild({\n  range: {\n    from: 'Br',\n    to: 'Da'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName + '; firstName: ' + node.value);\n});\nconsole.log('------------');\nconsole.log('Names from Br to Db');\nz.forEachChild({\n  range: {\n    from: 'Br',\n    to: 'Db'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName + '; firstName: ' + node.value);\n});\nconsole.log('------------');\nconsole.log('Names from Briggs to Davis');\nz.forEachChild({\n  range: {\n    from: 'Briggs',\n    to: 'Davis'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName + '; firstName: ' + node.value);\n});\nconsole.log('------------');\nconsole.log('Names from B to D');\nz.forEachChild({\n  range: {\n    from: 'B',\n    to: 'D'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName + '; firstName: ' + node.value);\n});\nconsole.log('------------');\n```\nResponse:\n```\nNames from Br to Da\nLastName: Briggs; firstName: A\nLastName: Davies; firstName: D\nLastName: Davis; firstName: T\n------------\nNames from Br to Db\nLastName: Briggs; firstName: A\nLastName: Davies; firstName: D\nLastName: Davis; firstName: T\n------------\nNames from Briggs to Davis\nLastName: Briggs; firstName: A\nLastName: Davies; firstName: D\nLastName: Davis; firstName: T\n------------\nNames from B to D\nLastName: Barton; firstName: J\nLastName: Briggs; firstName: A\nLastName: Davies; firstName: D\nLastName: Davis; firstName: T\nLastName: Douglas; firstName: N\n```\n\nUsing only `from` or `to`:\n```js\nconsole.log('Names from B');\nz.forEachChild({\n  range: {\n    from: 'B'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName);\n});\nconsole.log('------------');\nconsole.log('Names from D');\nz.forEachChild({\n  range: {\n    from: 'D'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName);\n});\nconsole.log('------------');\nconsole.log('Names to D');\nz.forEachChild({\n  range: {\n    to: 'D'\n  }\n}, function (lastName, node) {\n  console.log('LastName: ' + lastName);\n});\nconsole.log('------------');\n```\nResponse:\n```\nNames from B\nLastName: Barton\nLastName: Briggs\nLastName: Davies\nLastName: Davis\nLastName: Douglas\nLastName: a\nLastName: b\nLastName: c\nLastName: d\n------------\nNames from D\nLastName: Davies\nLastName: Davis\nLastName: Douglas\nLastName: a\nLastName: b\nLastName: c\nLastName: d\n------------\nNames to D\nLastName: Barton\nLastName: Briggs\nLastName: Davies\nLastName: Davis\nLastName: Douglas\n```\n\n#### \u003ca id=\"toe-foreachleafnode\"\u003e\u003c/a\u003e forEachLeafNode\n\nThere is another forEach method loop through each leaf node - `forEachLeafNode`\n```js\nconsole.log('forEachLeafNode through rob global:');\nrob.forEachLeafNode(function (value) {\n  console.log(value);\n});\n```\nResponse:\n```\nforEachLeafNode through rob global:\n1\nhello\nworld\nJ\nA\nD\nT\nN\nthis is a\nthis is b\na\ns\nd\na\nb\n```\n\n### \u003ca id=\"toe-traversing-document-nodes\"\u003e\u003c/a\u003e Traversing Document Nodes\n\n#### \u003ca id=\"toe-traversing-countChildren\"\u003e\u003c/a\u003e countChildren\n\nWants to know children count of document node?\n```js\nconsole.log('Number of children: ' + rob.countChildren());\n```\nResponse:\n```\nNumber of children: 5\n```\n\n#### \u003ca id=\"toe-traversing-$\"\u003e\u003c/a\u003e $()\n\nLet's look deeper to $() function\n\n```js\nvar robx = rob.$('x', true);\nconsole.log('robx: ' + robx.value);\nconsole.log(JSON.stringify(rob, null, 2));\nconsole.log('===============');\nconsole.log(JSON.stringify(robx, null, 2));\n```\n\nResponse:\n```\nrobx: hello\n{\n  \"documentStore\": {\n    \"db\": {},\n    \"build\": {\n      \"no\": \"1.16.0\",\n      \"date\": \"7 September 2017\"\n    },\n    \"domain\": null,\n    \"_events\": {},\n    \"_eventsCount\": 1\n  },\n  \"name\": \"rob\",\n  \"isDocumentNode\": true,\n  \"path\": [],\n  \"documentName\": \"rob\",\n  \"_node\": {\n    \"global\": \"rob\",\n    \"subscripts\": []\n  },\n  \"$x\": {\n    \"documentStore\": {\n      \"db\": {},\n      \"build\": {\n        \"no\": \"1.16.0\",\n        \"date\": \"7 September 2017\"\n      },\n      \"domain\": null,\n      \"_events\": {},\n      \"_eventsCount\": 1\n    },\n    \"name\": \"x\",\n    \"isDocumentNode\": false,\n    \"path\": [\n      \"x\"\n    ],\n    \"documentName\": \"rob\",\n    \"_node\": {\n      \"global\": \"rob\",\n      \"subscripts\": [\n        \"x\"\n      ],\n      \"data\": \"hello\"\n    }\n  },\n  \"$y\": {\n    \"documentStore\": {\n      \"db\": {},\n      \"build\": {\n        \"no\": \"1.16.0\",\n        \"date\": \"7 September 2017\"\n      },\n      \"domain\": null,\n      \"_events\": {},\n      \"_eventsCount\": 1\n    },\n    \"name\": \"y\",\n    \"isDocumentNode\": false,\n    \"path\": [\n      \"y\"\n    ],\n    \"documentName\": \"rob\",\n    \"_node\": {\n      \"global\": \"rob\",\n      \"subscripts\": [\n        \"y\"\n      ],\n      \"data\": \"world\"\n    }\n  },\n  \"$a\": {\n    \"documentStore\": {\n      \"db\": {},\n      \"build\": {\n        \"no\": \"1.16.0\",\n        \"date\": \"7 September 2017\"\n      },\n      \"domain\": null,\n      \"_events\": {},\n      \"_eventsCount\": 1\n    },\n    \"name\": \"a\",\n    \"isDocumentNode\": false,\n    \"path\": [\n      \"a\"\n    ],\n    \"documentName\": \"rob\",\n    \"_node\": {\n      \"global\": \"rob\",\n      \"subscripts\": [\n        \"a\"\n      ],\n      \"data\": 0\n    }\n  },\n  \"$z\": {\n    \"documentStore\": {\n      \"db\": {},\n      \"build\": {\n        \"no\": \"1.16.0\",\n        \"date\": \"7 September 2017\"\n      },\n      \"domain\": null,\n      \"_events\": {},\n      \"_eventsCount\": 1\n    },\n    \"name\": \"z\",\n    \"isDocumentNode\": false,\n    \"path\": [\n      \"z\"\n    ],\n    \"documentName\": \"rob\",\n    \"_node\": {\n      \"global\": \"rob\",\n      \"subscripts\": [\n        \"z\"\n      ]\n    }\n  }\n}\n===============\n{\n  \"documentStore\": {\n    \"db\": {},\n    \"build\": {\n      \"no\": \"1.16.0\",\n      \"date\": \"7 September 2017\"\n    },\n    \"domain\": null,\n    \"_events\": {},\n    \"_eventsCount\": 1\n  },\n  \"name\": \"x\",\n  \"isDocumentNode\": false,\n  \"path\": [\n    \"x\"\n  ],\n  \"documentName\": \"rob\",\n  \"_node\": {\n    \"global\": \"rob\",\n    \"subscripts\": [\n      \"x\"\n    ],\n    \"data\": \"hello\"\n  }\n}\n```\n\n### \u003ca id=\"toe-traversing-parent\"\u003e\u003c/a\u003e parent\n\n```js\nvar roby = rob.$x.$('y');\nconsole.log('parent: ' + roby.parent.value);\n```\nResponse:\n```\nparent: hello\n```\n\n#### \u003ca id=\"toe-traversing-firstChild-nextSibling\"\u003e\u003c/a\u003e firstChild / nextSibling\n\n```js\nvar first = rob.firstChild;\nconsole.log('first: ' + first.name);\nconsole.log('next = ' + first.nextSibling.name);\n```\nResponse:\n```\nfirst: a\nnext = x\n```\n\n#### \u003ca id=\"toe-traversing-lastChild-previousSibling\"\u003e\u003c/a\u003e lastChild / previousSibling\n\n```js\nvar last = rob.lastChild;\nconsole.log('last: ' + last.name);\nconsole.log('previous = ' + last.previousSibling.name);\n```\nResponse:\n```\nlast: z\nprevious = y\n```\n\n#### \u003ca id=\"toe-traversing-value\"\u003e\u003c/a\u003e value\n\n```js\nconsole.log('temp before: ' + temp.value);\ntemp.value = 1234;\nconsole.log('temp after: ' + temp.value);\n```\nResponse:\n```\ntemp before:\ntemp after: 1234\n```\n\n#### \u003ca id=\"toe-traversing-delete\"\u003e\u003c/a\u003e delete\n\n```js\ntemp.delete()\nconsole.log('temp after delete: ' + temp.value);\n```\nResponse:\n```\ntemp after delete:\n```\n\n### \u003ca id=\"toe-gets-list-of-globals\"\u003e\u003c/a\u003e Gets a List of Globals\n\n```js\nvar list = documentStore.list();\nconsole.log(JSON.stringify(list));\n```\nResponse:\n```\n[\"rob\",\"temp\"]\n```\n\n## \u003ca id=\"toe-worker-module-example-and-express-integration-using-ewd-qoper-express\"\u003e\u003c/a\u003eCaché Worker Module Example and Express Integration using ewd-qoper8-express\n\nHere's an example of ewd-document-store integrating with [ewd-qoper8-express](https://github.com/robtweed/ewd-qoper8-express) and [ewd-qoper8](https://github.com/robtweed/ewd-qoper8). You'll find this in the /examples directory - look for CacheExpress.js and CacheModule.js:\n\nCacheExpress.js\n\n```js\nvar express = require('express');\nvar bodyParser = require('body-parser');\nvar qoper8 = require('ewd-qoper8');\nvar qx = require('ewd-qoper8-express');\n\nvar app = express();\napp.use(bodyParser.json());\n\nvar q = new qoper8.masterProcess();\nqx.init(q);\n\napp.post('/qoper8', function (req, res) {\n  q.handleMessage(req.body, function (resultObj) {\n    delete resultObj.finished;\n    res.send(resultObj);\n  });\n});\n\napp.get('/', function (req, res) {\n  res.sendFile(__dirname + '/index.html');\n});\n\nq.on('start', function () {\n  this.worker.module = process.cwd() + '/examples/CacheModule';\n});\n\nq.on('started', function () {\n  var server = app.listen(8080, function () {\n    var host = server.address().address;\n    var port = server.address().port;\n\n    console.log('EWD-Express listening at http://%s:%s', host, port);\n    console.log('__dirname = ' + __dirname);\n  });\n\n  var io = require('socket.io')(server);\n  io.on('connection', function (socket) {\n    socket.on('my-request', function (data) {\n      q.handleMessage(data, function (resultObj) {\n        delete resultObj.finished;\n        socket.emit('my-response', resultObj);\n      });\n    });\n  });\n});\n\nq.start();\n```\n\nCacheModule.js:\n```js\nvar DocumentStore = require('ewd-document-store');\nvar Cache = require('cache').Cache;\n\nmodule.exports = function () {\n\n  this.on('start', function (isFirst) {\n    // establish the connection to Cache database\n\n    this.db = new Cache();\n\n    var ok = this.db.open({\n      path: process.env.CACHE_MGR_PATH || '/opt/cache/mgr',\n      username: process.env.CACHE_USERNAME || '_SYSTEM',\n      password: process.env.CACHE_PASSWORD || 'SYS',\n      namespace: process.env.CACHE_NAMESPACE || 'USER'\n    });\n\n    console.log('ok: ' + JSON.stringify(ok));\n\n    this.documentStore = new DocumentStore(this.db);\n\n    // Example of handler for the afterSet event which is fired every time a GlobalNode value changes:\n    this.documentStore.on('afterSet', function (node) {\n      console.log('afterSet: ' + JSON.stringify(node));\n    });\n\n    //  Clear down the requests global when ewd-qoper8 first started:\n    if (isFirst) {\n      var glob = new this.documentStore.DocumentNode('requests');\n      glob.delete();\n    }\n  });\n\n  this.on('message', function(messageObj, send, finished) {\n\n    // For example - save every incoming message object to the requests global\n    var glob = new this.documentStore.DocumentNode('requests', [process.pid]);\n    var ix = glob.increment();\n\n    glob.$(ix).setDocument(messageObj);\n\n    var results = {\n      hello: 'from worker ' + process.pid,\n      time: new Date().toString(),\n      message: messageObj\n    };\n    finished(results);\n  });\n\n  this.on('stop', function() {\n    // Make sure the connection to Cache is closed before the child process closes;\n    console.log('Worker ' + process.pid + ' closing database');\n    this.db.close();\n  });\n};\n```\n\nLet's this example: `$ node examples/CacheExpress.js`\n\n\u003e Note: You may need to run this as sudo due to Cache permissions\n\n    \n    curl -X POST http:/127.0.0.1:8080/qoper8\n    \nResponse:\n```\n{\n  \"message\": {\n    \"hello\": \"from worker 48900\",\n    \"time\": \"Tue Sep 12 2017 13:38:18 GMT+0000 (GMT)\",\n    \"message\": {}\n  }\n}\n```\n\n### \u003ca id=\"toe-using-websockets\"\u003e\u003c/a\u003eUsing WebSockets\n\nIn order to test this example, you need to load an HTML file - there's one already created in the /examples folder (index.html). If you start the example above and put the following URL into a browser: \u003chttp://127.0.0.1:8080/\u003e (change the IP address as appropriate), it should load the index.html page. This loads the client-side socket.io library and otherwise just contains a button that contains the text \"Click Me”\n\nWhen the button is clicked it will send a web socket message to Express/socket.io, and will show the returned response web socket message in the browser's Javascript console. It should look something like this:\n```json\newd-qoper8 message received: {\n  \"type\": \"testSocketRequest\",\n  \"message\": {\n    \"youSent\": {\n      \"type\": \"testSocketRequest\",\n      \"hello\": \"world\"\n    },\n    \"workerSent\": \"hello from worker 13912\",\n    \"time\": \"Wed Mar 02 2016 09:04:38 GMT+0000 (GMT)\"\n  }\n}\n```\nIn the same time, you may see the following in console output:\n```\nafterSet: {\"documentName\":\"requests\",\"path\":[50622],\"before\":{\"value\":\"\",\"exists\":false},\"value\":\"1\"}\nafterSet: {\"documentName\":\"requests\",\"path\":[50622,\"1\",\"type\"],\"before\":{\"value\":\"\",\"exists\":false},\"value\":\"testSocketRequest\"}\nafterSet: {\"documentName\":\"requests\",\"path\":[50622,\"1\",\"hello\"],\"before\":{\"value\":\"\",\"exists\":false},\"value\":\"world\"}\nTue, 12 Sep 2017 10:55:11 GMT; master process received response from worker 50622: {\"type\":\"testSocketRequest\",\"finished\":true,\"message\":{\"hello\":\"from worker 50622\",\"time\":\"Tue Sep 12 2017 13:55:11 GMT+0000 (GMT)\",\"message\":{\"type\":\"testSocketRequest\",\"hello\":\"world\"}}}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtweed%2Fewd-document-store-examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobtweed%2Fewd-document-store-examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtweed%2Fewd-document-store-examples/lists"}