Thijs
Thijs

Reputation: 1546

MarkLogic 8 JavaScript Arrays

I'm trying to work with arrays. This is some working code that explains what I am doing.

// query

var a = ["1000", "2000", "3000"];
var b = ["2000"];    

for (i in b) {
  var index = a.indexOf(b[i]);
};

if (index > -1) {
    a.splice(index, 1);
};

a

Now when I use this same logic for my query results, it does not work anymore.

// query

queryDo = cts.andQuery([
      cts.jsonPropertyValueQuery("displayable", "true"),
      cts.jsonPropertyValueQuery("section", "dikw Track Events"),
      cts.jsonPropertyValueQuery("name", 'dikw_default'),
      cts.collectionQuery(["reference/application"])
    ]);

queryDont = cts.andQuery([
      cts.jsonPropertyValueQuery("displayable", "false"),
      cts.jsonPropertyValueQuery("section", "dikw Track Events"),
      cts.jsonPropertyValueQuery("name", 'Helpdesk'),
      cts.collectionQuery(["reference/application"])
    ]);

var qDo = cts.jsonPropertyWords("code", null, "document", queryDo).toArray();
var qDont = cts.jsonPropertyWords("code", null, "document", queryDont).toArray();

for (i in qDont) {
  var index = qDo.indexOf(qDont[i]);
};

if (index > -1) {
    qDo.splice(index, 1);
};

qDo

I've verified that the result of both queries is an array. The arrays consist of values just like the example code; 1000, 2000, etc. Also, when I use a notAndQuery to exclude results from the 2nd query from the first, this has no effect.

When I look at qDo[2] for example, the right value is returned.

My andNotQuery:

queryDo = cts.andQuery([
      cts.jsonPropertyValueQuery("displayable", "true"),
      cts.jsonPropertyValueQuery("section", "dikw Track Events"),
      cts.jsonPropertyValueQuery("name", 'dikw_default'),
      cts.collectionQuery(["reference/application"])
    ]);

queryDont = cts.andQuery([
      cts.jsonPropertyValueQuery("displayable", "false"),
      cts.jsonPropertyValueQuery("section", "dikw Track Events"),
      cts.jsonPropertyValueQuery("name", 'Helpdesk'),
      cts.collectionQuery(["reference/application"])
    ]);

andnot = cts.andNotQuery(queryDo, queryDont);

result = cts.jsonPropertyWords("code", null, "document", andnot);

Upvotes: 2

Views: 184

Answers (3)

Thijs
Thijs

Reputation: 1546

After filing a bug at MarkLogic I got this repsonse from the engineering team:

"The return from the lexicon call is a StringWithFrequency (not just a String) so the JS layer wraps it"

You can create an Array from the call to cts.jsonPropertyWords as you did before, but you'll need to iterate through and get the string values for each item in turn first. Something like this:

  1. Create the Array from cts.jsonPropertyWords as before
  2. Create a new Array
  3. Iterate through the original Array and push each items's string value into the new Array. The call to indexOf will work on the new Array.

Work around

var trackCodes = cts.jsonPropertyWords("code", null, "document", cts.andQuery([])).toArray();
var tc2 = new Array();

for (var i = 0; i < trackCodes.length; i++){
  tc2.push(trackCodes[i].toString())
}

tc2.indexOf(["your value"])

Upvotes: 0

ehennum
ehennum

Reputation: 7335

The for/in operator may not be iterating over the array in the way you expect:

"There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited."

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

In addition, for/in may inhibit optimization in v8:

https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#5-for-in

If you use the familiar for (var i=0; i < array.length; i++) {...} statement, does that produce the expected results?

Hoping that helps,

Upvotes: 3

grtjn
grtjn

Reputation: 20414

I think there is a flaw in your logic. The if at the end seems misplaced. If you extend your example with the number to include another value, it goes wrong:

var a = ["1000", "2000", "3000", "4000"];
var b = ["2000", "3000"];    

for (i in b) {
  var index = a.indexOf(b[i]);
};

if (index > -1) {
    a.splice(index, 1);
};

a

Instead, the if should be within the for loop:

var a = ["1000", "2000", "3000", "4000"];
var b = ["2000", "3000"];    

for (i in b) {
  var index = a.indexOf(b[i]);

  if (index > -1) {
      a.splice(index, 1);
  };
};

a

But it could be worthwhile to explore using a notQuery in some way. Depending on the layout of your data, that could work. That would be much more efficient as well, as you wouldn't have to do custom filtering after the searches.

HTH!

Upvotes: 2

Related Questions