Implement For Loop in Marklogic Javascript?

落爺英雄遲暮 提交于 2019-12-11 07:55:56

问题


I can get all the URIs of the documents in a collection by using below XQuery:

for $doc in fn:collection("transform") 
return xdmp:node-uri($doc)

But, when I tried to implement this in a Javascript module in MarkLogic, it is getting only last document in the database collection.

'use strict';
declareUpdate()
var docs = fn.collection("transform");
for(var doc of docs) {
  xdmp.nodeUri(doc)
}

It is not giving all the URIs in the collection, but rather it's only returning the last URI of the document.

How can I get it to return all of the URIs?


回答1:


Create an array and add each of the URIs to that array in your for loop, then either return the array:

'use strict';
declareUpdate()
var docs = fn.collection("transform");
var results = [];
for (var doc of docs) {
 results.push(xdmp.nodeUri(doc));
}
results;

or return a Sequence using Sequence.from():

'use strict';
declareUpdate()
var docs = fn.collection("transform");
var results = [];
for (var doc of docs) {
 results.push(xdmp.nodeUri(doc));
}
Sequence.from(results);

However, if you simply want to return the URIs, then it would be better/easier to use cts.uris() with a cts.collectionQuery():

'use strict';
declareUpdate();
cts.uris("", null, cts.collectionQuery("transform"));



回答2:


None of the answers explain why they address the origin question, or what the core misunderstanding is. They are correct answers but its not obvious why.

There is no problem with the original code except the incorrect assumption of how JavaScript returns evaluated expressions.

The LAST evaluated expression is returned from a JavaScript 'script'.

This differs from XQuery in which the expressions accumulate into a Sequence which is returned.

Try this simple case:

'use strict;'
var i = 0
i++
i++
i++

Result:

2

NOT

[ 0 , 1 , 2 ]

That doesnt mean it didnt 'execute' "i++" 3 times, it means the resulting value is the last one.

Try your original code unchanged except in the loop 'Do Something' that has some kind of visible result -- say Console.log()

'use strict';
declareUpdate()
var docs = fn.collection("transform");
for(var doc of docs) {
  Console.log(xdmp.nodeUri(doc))
}

Then look in ErrorLog.txt (V8) of 8000_ErrorLog.txt (V9) You will see an entry for each URI.

That is WHY the suggestion to put the values into an array, since you asked "How can I get it to return all of the URIs?" - thats how you do it.

However the question "Is there any way to read directly the uri's rather than pushing into array" is entirely different. Your existing code currently does that. You just don't 'see' it because you are doing nothing with the URI but 'dropping it on the floor'

When you add the code to do whatever it is you want to do with the URI (or node), it will be executed one by one without having to load the entire sequence first.

Try it.



来源:https://stackoverflow.com/questions/48307852/implement-for-loop-in-marklogic-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!