简体   繁体   中英

retrieving all objects in an array JS

I'm working in ServiceNow and trying to set up an array that retrieves all of the knowledge articles relevant to a user. My code below is only returning one of the articles and I'm not sure why...any suggestions?

var kaArray = [];
var ka = new GlideRecord('my_knowledge');
ka.addQuery('workflow_state', 'Published');
ka.addQuery('kb_category.label', 'Benefits');
ka.addQuery('occ_series', 'CONTAINS', occ)
  .addOrCondition('location', 'CONTAINS', loc)
  .addOrCondition(
    ka.addNullQuery('location') && ka.addNullQuery('occ_series')
  );    
ka.orderByDesc('sys_updated_on');
ka.query();
while(ka.next()) {
    obj = {number: ka.number.toString(),
           short_desc: ka.short_description.toString(),
           url: 'kb_view.do?sysparm_article=' + ka.number}; 
    kaArray.push(obj);
}

There are several things that I'd recommend, one of which is probably the solution to your problem.

  1. You're using "&&", a conditional operator, to.. well I'm afraid I'm not totally sure. You cannot do this in JavaScript in the way you're attempting to. Also, Since .addOrCondition() does not return a value that you would want to use as a bool), this won't work. Instead, just put the next command on the next line. I'll show you a finished version of your code at the bottom.

  2. Instead of these complicated sequences of .addNullQuery() , addQuery() , and .addOrCondition() calls, simply navigate to the table you're interested in filtering, and literally build the filter there in the condition builder. Then, right-click the final filter breadcrumb, and click "copy query", then use .addEncodedQuery() . Like so:

复制查询 gr.addEncodedQuery('short_descriptionLIKEeclipse^kb_category=c78a2d2047b002007f47563dbb9a71bf^workflow_state=published' / The result of clicking "copy query" /);

  1. Why are you using a scoped app and custom table? The scoped app makes sense if you're planning to list it on the market, but based on the table name, it sounds like it's for a specific business. I recommend a global app, if anything. I also very strongly recommend, whether scoped or global, that you simply create a new knowledgebase rather than creating a whole new table, unless you had some advanced functionality you'll need on this KB and are willing to sacrifice a great deal of OOB functionality to get it. Not saying what you're doing is wrong, just want to make sure you're aware of the hassle you might be creating for yourself down the line. :-)

  2. From what I can see, you don't, with your CURRENT configuration, have to worry about JavaScript's pass-by-reference idiosyncrasies, I don't see you declare "obj" anywhere. You might want to do that, and give it a better name. You might want to funtionalize your addition of that object to the array though. If #5 isn't right, then the problem is most likely due to a pass-by-ref issue that I missed, at least that's my guess. I can see that you've got at least one pass-by-ref issue on the third line inside your while loop:

    url: 'kb_view.do?sysparm_article=' + ka.number};

Always use "getters and setters". That is to say, when you want a value from a GlideRecord, never directly reference gr.fieldName . Instead, use gr.getValue('fieldName'); . As one alternative (which I don't like but have no rational reason not to) you can also use .toString() , as you have in a few other places. This explicitly casts the value to a string rather than the Object that it is (a GlideElement object). I don't really like this because it means that you're force-casting an OBJECT to a STRING. There is no EASY path to doing that, so it relies on a built-in method of the GlideElement class to override the .toString method of most other types.

  1. I'm betting that this query, the way it's written anyway, is returning only one record. You can easily test this by using something like gs.info('Looking through ' + ka.getRowCount() + ' records.'); after the query.

For you, I humbly recommend " Learning ServiceNow ". Full disclosure, this is my own book. That said, I've tailored this book specifically for people who are at EXACTLY your level of knowledge and experience, and I think that you would get a lot out of it. Most SN devs would get a lot out of it, but I think you are in a particular position to get the most out of it. I know it says June 9th, but this should be releasing by the end of this month or within a few days of there.

Here's a version of what I think you're trying to do, that ought to work. I'm sure that the query will need a little tweaking - I had to kind of guess at what you were going for, but I think the use of ^NQ is closest to what you were looking to accomplish. Like I said, just build your query on the table, then copy it into encQuery (and replace my existing logic/return your proper query from buildEncQuery). Here it is:

 /**
 * encQuery will hold the temporary and final encoded query strings, which will look something like this (when finished):
 * "workflow_state=published^kb_category.label=Benefits^federal_occ_seriesLIKEOCC_HERE^ORlocationLIKELOC_HERE^NQworkflow_state=published^kb_category.label=Benefits^locationISEMPTY^federal_occ_seriesISEMPTY"
 * @type {String}
 */
var encQuery = buildEncQuery(occ, loc); //occ and loc were used in your original queries, so I assume they're variables that are available to you in this scope at this point in your script. 
/**
 * An array of objects, each containing data about knowledge articles returned from our query using encQuery.
 * @type {{name: string, short_desc: string, url: string}[]}
 */
var knowledgeArray = [];
/**
 * The GR we're iterating over
 * @type {GlideRecord}
 */
var knowledgeGR = new GlideRecord('x_81991_federal_hc_federal_knowledge');
knowledgeGR.addEncodedQuery(encQuery);
knowledgeGR.orderByDesc('sys_updated_on');
knowledgeGR.query();
while (knowledgeGR.next()) {
    knowledgeArray.push({
                     number:     knowledgeGR.getValue('number'),
                     short_desc: knowledgeGR.getValue('short_description'),
                     url:        'kb_view.do?sysparm_article=' + knowledgeGR.getValue('number')
                 });
}
gs.info('Located ' + knowledgeGR.getRowCount() + ' records. Array length: ' + knowledgeArray.length + '.');
//Done

/**
 * Builds the encoded query for the calling function.
 * @param occ {*}
 * @param loc {*}
 * @returns {string}
 */
function buildEncQuery(occ, loc) {
    if (occ === undefined || loc === undefined) {
        return;
    }
    var encQuery = 'workflow_state=published^kb_category.label=Benefits'
    encQuery += '^federal_occ_seriesLIKE' + occ + '^ORlocationLIKE' + loc + '^NQ' + encQuery + '^locationISEMPTY^federal_occ_seriesISEMPTY';
    return encQuery;
}

EDIT: I notice you're posting in StackOverflow a lot. However, you don't seem to be marking your questions as answered once they are. I recommend that you do that, but I also recommend that you check out sndevs.slack.com . It's a great community of other ServiceNow developers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM