{"id":13635,"date":"2022-08-04T16:02:15","date_gmt":"2022-08-04T23:02:15","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=13635"},"modified":"2025-06-13T17:20:44","modified_gmt":"2025-06-14T00:20:44","slug":"from-n1ql-to-javascript-and-back-part-3","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/","title":{"rendered":"From N1QL to JavaScript and Back &#8211; Part 3: Iterating over Documents and DML"},"content":{"rendered":"<p><a href=\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-2\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">This earlier blog<\/span><\/a><span style=\"font-weight: 400;\"> goes through the basics of executing N1QL statements inside JavaScript functions.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We now move onto\u2026<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Iterators\/Processing values<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">So far we have purposely avoided statements that return data, and returning data from the function.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is where we start exploring gathering data.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The <em>N1QL()<\/em> function, referenced directly, or via the transpiler magic, returns a statement handle. The handle comes in the form of a JavaScript object and has an associated iterator, for example:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true\">\u00a0\u00a0\u00a0\u00a0var q = SELECT * FROM b1;<\/pre>\n<p><span style=\"font-weight: 400;\">I will not spend lots of time on describing iterators, so here are the basics:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">You can get the next value from an iterator using the <\/span><span style=\"font-weight: 400;\">next()<\/span><span style=\"font-weight: 400;\"> method.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">done<\/span><span style=\"font-weight: 400;\"> property is true if there are no more documents to get.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Though you can use the iterator&#8217;s <\/span><em><span style=\"font-weight: 400;\">next()<\/span><\/em><span style=\"font-weight: 400;\"> and <\/span><em><span style=\"font-weight: 400;\">done<\/span><\/em><span style=\"font-weight: 400;\"> members in a while loop to get all the documents, a more readable construct is the <\/span><em><span style=\"font-weight: 400;\">for..of<\/span><\/em><span style=\"font-weight: 400;\"> loop over the statement handle itself.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Not all values need to be retrieved &#8211; you can discard a statement at any time by calling the statement&#8217;s <\/span><em><span style=\"font-weight: 400;\">close()<\/span><\/em><span style=\"font-weight: 400;\"> method, although, as we&#8217;ll see later, you don&#8217;t need to do this at all.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Putting it all together:<\/span><br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13636 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/08\/image_2022-08-04_152817169.png\" alt=\"Basics of iterators in N1QL\/JavaScript and Couchbase\" width=\"655\" height=\"215\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/image_2022-08-04_152817169.png 655w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/image_2022-08-04_152817169-300x98.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/image_2022-08-04_152817169-20x7.png 20w\" sizes=\"auto, (max-width: 655px) 100vw, 655px\" \/><br \/>\n<span style=\"font-weight: 400;\">and the corresponding function:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">CREATE FUNCTION doSelect() LANGUAGE JAVASCRIPT AS \"doSelect\" AT \"udfblog\";<\/pre>\n<p><span style=\"font-weight: 400;\">In this example, an array named <\/span><em><span style=\"font-weight: 400;\">res<\/span><\/em><span style=\"font-weight: 400;\"> accumulates the documents we obtain from <\/span><span style=\"font-weight: 400;\"><em>b1<\/em> <\/span><span style=\"font-weight: 400;\">through the iterator <\/span><em><span style=\"font-weight: 400;\">q<\/span><\/em><span style=\"font-weight: 400;\">, and it is then used to return them to the caller.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">A couple of side notes<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">In general terms, it probably is a better idea to process query values as they are received in the <\/span><span style=\"font-weight: 400;\">for<\/span><span style=\"font-weight: 400;\"> loop, rather than just accumulating them in an array, as this has transient memory usage implications.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Conversely, returning an array value from a function allows a statement to select from the function, for example:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">SELECT * FROM doSelect() AS funcDocs;<\/pre>\n<p><span style=\"font-weight: 400;\">This is much like you would do with table functions or collection derived tables which you have encountered in the relational world.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In the N1QL world these are known as <\/span><i><span style=\"font-weight: 400;\">expression scans<\/span><\/i><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Of course, it goes by itself that if all you want your function to do is return some documents from a<\/span><i><span style=\"font-weight: 400;\"> keyspace<\/span><\/i><span style=\"font-weight: 400;\"> without any further logic, you are probably better off just writing an inline function.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Back to the iterator!<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Once you have finished processing the values, the iterator closes itself automatically, so there&#8217;s nothing that you have to do.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If the iterator is not drained, it is good practice to close it, although this is not strictly necessary, as it will be automatically closed when the function returns, as well as in other circumstances as we&#8217;ll see later.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Inside the <\/span><span style=\"font-weight: 400;\"><em>for \u2026 of<\/em> \u2026<\/span><span style=\"font-weight: 400;\"> loop it is perfectly valid to have other N1QL statements: some things to be considered will be described in later sections.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Processing values<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Let&#8217;s try and use the values returned by the select, rather than just returning them:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true\">function doSelect() {\r\n\u00a0\u00a0\u00a0\u00a0var q = SELECT * FROM b1 LIMIT 2;\r\n\u00a0\u00a0\u00a0\u00a0var res = [];\r\n\u00a0\u00a0\u00a0\u00a0for (const doc of q) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let f1 = doc.f1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.push(f1);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0return res;\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Nothing particularly fancy, just extracting a field from the document.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Executing this function yields:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true\">[\r\n\u00a0\u00a0[\r\n\u00a0\u00a0\u00a0\u00a0null,\r\n\u00a0\u00a0\u00a0\u00a0null\r\n\u00a0\u00a0]\r\n]<\/pre>\n<p><span style=\"font-weight: 400;\">What gives? Why does it not return <em>f1<\/em>?<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can guess the answer by executing:<\/span><\/p>\n<pre class=\"lang:default decode:true \">SELECT * FROM b1 LIMIT 2<\/pre>\n<p><span style=\"font-weight: 400;\">And seeing, in the UI:<\/span><\/p>\n<pre class=\"lang:js decode:true\">[\r\n\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\"b1\": {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"f1\": 1\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0},\r\n\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\"b1\": {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"f1\": 2\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0}\r\n]<\/pre>\n<p><em><span style=\"font-weight: 400;\">f1<\/span><\/em><span style=\"font-weight: 400;\"> is a field in <\/span><em><span style=\"font-weight: 400;\">b1<\/span><\/em><span style=\"font-weight: 400;\">, not the selected document!<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Any of those does what you want:<\/span><\/p>\n<pre class=\"lang:js decode:true\">function doSelect() {\r\n\u00a0\u00a0\u00a0\u00a0var q = SELECT * FROM b1 LIMIT 2;\r\n\u00a0\u00a0\u00a0\u00a0var res = [];\r\n\u00a0\u00a0\u00a0\u00a0for (const doc of q) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let f1 = doc.b1.f1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.push(f1);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0return res;\r\n}<\/pre>\n<pre class=\"lang:js decode:true\">function doSelect() {\r\n\u00a0\u00a0\u00a0\u00a0var q = SELECT raw b1 FROM b1 LIMIT 2;\r\n\u00a0\u00a0\u00a0\u00a0var res = [];\r\n\u00a0\u00a0\u00a0\u00a0for (const doc of q) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let f1 = doc.f1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.push(f1);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0return res;\r\n}\r\n\r\nfunction doSelect() {\r\n\u00a0\u00a0\u00a0\u00a0var q = SELECT f1 FROM b1 LIMIT 2;\r\n\u00a0\u00a0\u00a0\u00a0var res = [];\r\n\u00a0\u00a0\u00a0\u00a0for (const doc of q) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let f1 = doc.f1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.push(f1);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0return res;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"color: #343e47; font-family: Lato, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 50px;\">DML statements<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Consider the following function:<\/span><\/p>\n<pre class=\"lang:js decode:true\">function doCopy() {\r\n\u00a0\u00a0\u00a0\u00a0var q1 = INSERT INTO b1 (KEY UUID(), VALUE v) SELECT b1 AS v FROM b1;\r\n\u00a0\u00a0\u00a0\u00a0var q2 = DELETE FROM b1 WHERE LENGTH(meta().id) = 2;\r\n}<\/pre>\n<pre class=\"lang:default decode:true \">CREATE FUNCTION doCopy() LANGUAGE JAVASCRIPT AS \"doCopy\" AT \"udfblog\"<\/pre>\n<p><span style=\"font-weight: 400;\">This function creates new documents in <em>b1<\/em> copying them from existing documents and removes the old documents.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The fact that <\/span><em><span style=\"font-weight: 400;\">q1<\/span><\/em><span style=\"font-weight: 400;\"> and <\/span><em><span style=\"font-weight: 400;\">q2<\/span><\/em><span style=\"font-weight: 400;\"> are iterators, even when the statements do not return values shouldn&#8217;t be too much of a surprise: as we&#8217;ll see later, DML statements can return values, and even worse, the transpiler cannot always determine if values are being returned or not, hence the <em>N1QL()<\/em> function always returns an iterator.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The implication of this is that once the <em>N1QL()<\/em> call returns, the N1QL statement may very well be executing asynchronously in the background, leaving the JavaScript function free to execute other code before fetching data.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The <em>jsevaluator<\/em> removes any behavioural ambiguity by forcing statements that do not return values to execute immediately and serially, meaning that it will wait for each DML statement complete before the next statement starts.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">No action on the iterator is necessary, not even closing it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is consistent with the behaviour we instinctively expect: we want to finish inserting a copy of the existing documents before we start deleting the old ones &#8211; or we may not be making a copy of all of the original documents!<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">DML statements that return values<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">N1QL DML statements can be made to return values, as in the function below:<\/span><\/p>\n<pre class=\"lang:js decode:true\">function doCopy() {\r\n\u00a0\u00a0\u00a0\u00a0var q1 = INSERT INTO b1 (KEY UUID(), VALUE v) SELECT b1 AS v FROM b1 RETURNING meta().id, b1;\r\n\u00a0\u00a0\u00a0\u00a0var res = []\r\n\u00a0\u00a0\u00a0\u00a0for (const doc of q1) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.push(doc);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0var q2 = DELETE FROM b1 WHERE LENGTH(meta().id) = 2;\r\n\u00a0\u00a0\u00a0\u00a0return res;\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Returned results are processed in much the same way as for <em>SELECT<\/em> statements.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The major difference compared to DML statements that do not return results is that when no results are returned, all the changes to disk are made as soon as the statement returns, while when results are returned the statement progresses as each individual document is collected from the iterator: you have to process all the returned values for all the changes to make it to disk.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Again, the statement is executed asynchronously &#8211; so, as you collect each individual result, you should not assume that it is the last modification made to disk: more could have already been made, with the relevant results just queued waiting to be collected.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">As with DML statements that do not return results, those that do are executed serially, meaning that if you do not process all the results queued in the iterator by the time you start the next statement, the jsevaluator will complete the current statement discarding all unprocessed values.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Conclusion<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">We have covered processing documents through N1QL and executing data manipulation.<\/span><\/p>\n<p><strong>Next, we are going to see how to handle errors.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This earlier blog goes through the basics of executing N1QL statements inside JavaScript functions. We now move onto\u2026 Iterators\/Processing values So far we have purposely avoided statements that return data, and returning data from the function. This is where we [&hellip;]<\/p>\n","protected":false},"author":1782,"featured_media":13637,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,9327,1812],"tags":[2133,1543,8911],"ppma_author":[8924],"class_list":["post-13635","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-javascript","category-n1ql-query","tag-functions","tag-javascript","tag-udf"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.\" \/>\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\/from-n1ql-to-javascript-and-back-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML\" \/>\n<meta property=\"og:description\" content=\"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-04T23:02:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T00:20:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1707\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Marco Greco, Software Architect, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marco Greco, Software Architect, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\"},\"author\":{\"name\":\"Marco Greco, Software Architect, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2b5184a7cdb443ff2897aff0866cd6fd\"},\"headline\":\"From N1QL to JavaScript and Back &#8211; Part 3: Iterating over Documents and DML\",\"datePublished\":\"2022-08-04T23:02:15+00:00\",\"dateModified\":\"2025-06-14T00:20:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\"},\"wordCount\":949,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg\",\"keywords\":[\"functions\",\"javascript\",\"User Defined Function (UDF)\"],\"articleSection\":[\"Couchbase Server\",\"JavaScript\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\",\"name\":\"From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg\",\"datePublished\":\"2022-08-04T23:02:15+00:00\",\"dateModified\":\"2025-06-14T00:20:44+00:00\",\"description\":\"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg\",\"width\":2560,\"height\":1707,\"caption\":\"From N1QL to Javascript and back - Part 3: iterating over documents and DML\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"From N1QL to JavaScript and Back &#8211; Part 3: Iterating over Documents and DML\"}]},{\"@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\/2b5184a7cdb443ff2897aff0866cd6fd\",\"name\":\"Marco Greco, Software Architect, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/707c967b795fd71b6330f6d3118cf308\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6be0ee56851d2f71a554731d5edd5c820069680f0a810b47f094091c58bc553?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6be0ee56851d2f71a554731d5edd5c820069680f0a810b47f094091c58bc553?s=96&d=mm&r=g\",\"caption\":\"Marco Greco, Software Architect, Couchbase\"},\"description\":\"In a previous life, Marco used to be CTO, radiation physicist, software architect, sysadmin, DBA, trainer and general handyman at Italy's largest radiation theraphy practice. Having switched career and country, he spent more than two decades in various support and development positions in Informix first and IBM later, before finally taking the plunge and joining Couchbase, to help them make gold out of N1QL. He holds several patents and has authored open source projects of his own.\",\"sameAs\":[\"https:\/\/github.com\/marcogrecopriolo\",\"https:\/\/www.linkedin.com\/in\/marco-greco-7665308\/\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/marcocouchbase-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML - The Couchbase Blog","description":"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.","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\/from-n1ql-to-javascript-and-back-part-3\/","og_locale":"en_US","og_type":"article","og_title":"From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML","og_description":"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.","og_url":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/","og_site_name":"The Couchbase Blog","article_published_time":"2022-08-04T23:02:15+00:00","article_modified_time":"2025-06-14T00:20:44+00:00","og_image":[{"width":2560,"height":1707,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg","type":"image\/jpeg"}],"author":"Marco Greco, Software Architect, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Marco Greco, Software Architect, Couchbase","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/"},"author":{"name":"Marco Greco, Software Architect, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2b5184a7cdb443ff2897aff0866cd6fd"},"headline":"From N1QL to JavaScript and Back &#8211; Part 3: Iterating over Documents and DML","datePublished":"2022-08-04T23:02:15+00:00","dateModified":"2025-06-14T00:20:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/"},"wordCount":949,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg","keywords":["functions","javascript","User Defined Function (UDF)"],"articleSection":["Couchbase Server","JavaScript","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/","url":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/","name":"From N1QL to JavaScript and Back - Part 3: Iterating over Documents and DML - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg","datePublished":"2022-08-04T23:02:15+00:00","dateModified":"2025-06-14T00:20:44+00:00","description":"Learn the basics of iterators in N1QL\/Javascript and Couchbase, the corresponding function, processing documents through N1QL and executing data manipulation.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/n1ql-javascript-iterators-scaled.jpg","width":2560,"height":1707,"caption":"From N1QL to Javascript and back - Part 3: iterating over documents and DML"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/from-n1ql-to-javascript-and-back-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"From N1QL to JavaScript and Back &#8211; Part 3: Iterating over Documents and DML"}]},{"@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\/2b5184a7cdb443ff2897aff0866cd6fd","name":"Marco Greco, Software Architect, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/707c967b795fd71b6330f6d3118cf308","url":"https:\/\/secure.gravatar.com\/avatar\/e6be0ee56851d2f71a554731d5edd5c820069680f0a810b47f094091c58bc553?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6be0ee56851d2f71a554731d5edd5c820069680f0a810b47f094091c58bc553?s=96&d=mm&r=g","caption":"Marco Greco, Software Architect, Couchbase"},"description":"In a previous life, Marco used to be CTO, radiation physicist, software architect, sysadmin, DBA, trainer and general handyman at Italy's largest radiation theraphy practice. Having switched career and country, he spent more than two decades in various support and development positions in Informix first and IBM later, before finally taking the plunge and joining Couchbase, to help them make gold out of N1QL. He holds several patents and has authored open source projects of his own.","sameAs":["https:\/\/github.com\/marcogrecopriolo","https:\/\/www.linkedin.com\/in\/marco-greco-7665308\/"],"url":"https:\/\/www.couchbase.com\/blog\/author\/marcocouchbase-com\/"}]}},"authors":[{"term_id":8924,"user_id":1782,"is_guest":0,"slug":"marcocouchbase-com","display_name":"Marco Greco, Software Architect, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/e6be0ee56851d2f71a554731d5edd5c820069680f0a810b47f094091c58bc553?s=96&d=mm&r=g","author_category":"","last_name":"Greco","first_name":"Marco","job_title":"","user_url":"","description":"In a previous life, Marco used to be CTO, radiation physicist, software architect, sysadmin, DBA, trainer and general handyman at Italy's largest radiation theraphy practice.\r\n\r\nHaving switched career and country, he spent more than two decades in various support and development positions in Informix first and IBM later, before finally taking the plunge and joining Couchbase, to help them make gold out of N1QL.\r\n\r\nHe holds several patents and has authored open source projects of his own."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13635","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\/1782"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=13635"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/13635\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13637"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=13635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=13635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=13635"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=13635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}