javascriptxquerymarklogicmarklogic-9sjs

MarkLogic 9 Clusters - Restricting to certain fields with SJS


I am trying to implement a simple clustering application with MarkLogic 9 using server side Javascript. I have a pretty complicated custom query builder that is already implemented in JS so I would prefer to do it all in a .sjs file.

My problem is that I cannot figure out how to restrict the clustering search to only look at a few properties of a document (namely, "title" and "abstract"). None of the properties have children. I tried following the Shakespeare plays demo but it is implemented in XQuery.

My current implementation is a .xqy file that uses xdmp:javascript-eval to employ my js query builder. This works and successfully returns the results of the query using:

$qry-results := xdmp:javascript-eval(cts.search(someQueryVariable).toArray())

I assume that the issue is in my XQuery code that I sort of copied over from the Shakespeare example but I have been at it for many hours and I can't get it to work. Here is my XQuery as it stands now:

declare namespace db="http://marklogic.com/xdmp/database" ;
declare namespace cl="cts:cluster" ;
declare namespace dt="cts:distinctive-terms" ;
let $options-node :=
<options xmlns="cts:cluster" >
      <overlapping>false</overlapping>
      <label-max-terms>1</label-max-terms>
      <label-ignore-words>a of the when s as</label-ignore-words>
      <max-clusters>10</max-clusters>
      <!-- turn all database-level indexing options OFF - only use field terms -->
      <db:word-searches>false</db:word-searches>
      <db:stemmed-searches>false</db:stemmed-searches>
      <db:fast-case-sensitive-searches>false</db:fast-case-sensitive-searches>
      <db:fast-diacritic-sensitive-searches>false</db:fast-diacritic-sensitive-searches>
      <db:fast-phrase-searches>false</db:fast-phrase-searches>
      <db:phrase-throughs/>
      <db:phrase-arounds/>
      <db:fast-element-word-searches>false</db:fast-element-word-searches>
      <db:fast-element-phrase-searches>false</db:fast-element-phrase-searches>
      <db:element-word-query-throughs/>
      <db:fast-element-character-searches>false</db:fast-element-character-searches>
      <db:range-element-indexes/>
      <db:range-element-attribute-indexes/>
      <db:one-character-searches>false</db:one-character-searches>
      <db:two-character-searches>false</db:two-character-searches>
      <db:three-character-searches>false</db:three-character-searches>
      <db:trailing-wildcard-searches>false</db:trailing-wildcard-searches>
      <db:fast-element-trailing-wildcard-searches>false</db:fast-element-trailing-wildcard-searches>
      <db:fields>
        <field>
          <field-name>abstract</field-name>
            <include-root>true</include-root>
            <stemmed-searches>advanced</stemmed-searches>
            <db:fast-phrase-searches>true</db:fast-phrase-searches>
        </field>
        <field>
            <field-name>title</field-name>
            <include-root>true</include-root>
            <stemmed-searches>advanced</stemmed-searches>
            <db:fast-phrase-searches>true</db:fast-phrase-searches>
        </field>
        <field>
          <field-name>institution</field-name>
            <include-root>false</include-root>
            <stemmed-searches>advanced</stemmed-searches>
            <db:fast-phrase-searches>false</db:fast-phrase-searches>
        </field>
        <field>
            <field-name>researcher</field-name>
            <include-root>false</include-root>
            <stemmed-searches>advanced</stemmed-searches>
            <db:fast-phrase-searches>false</db:fast-phrase-searches>
        </field>
     </db:fields>
  </options>

let $res := cts:cluster( $qry-results, $options-node )/cts:cluster

return $res

And the error that I get most often is something like this:

XDMP-ARGTYPE: (err:XPTY0004) cts:cluster(json:array(<json:array xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" .../>...XDMP-CHILDNODEKIND: element nodes cannot have object node children...), <options xmlns="cts:cluster"><overlapping>false</overlapping><label-max-terms>...</label-max-terms>...</options>) -- arg1 is not of type node()*
in /cluster.xqy, at 113:12 [1.0-ml]
$qry-results = json:array(<json:array xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" .../>...XDMP-CHILDNODEKIND: element nodes cannot have object node children...)
$options-node = <options xmlns="cts:cluster"><overlapping>false</overlapping><label-max-terms>...</label-max-terms>...</options>

I am confident that it is something stupid but I am not experienced with XQuery so I can't make sense of it and I'm just banging my head against the wall right now.


Solution

  • If I understand correctly you'd like to implement the search in SJS, so you could just build your search in this way:

    cts.cluster(
        cts.search(cts.wordQuery('some terms')).toArray(),
        {
            overlapping: false,
            labelIgnoreWords: ['a', 'of', 'the', 'when', 's', 'as'],
            stemmedSearches: false,
            fastPhraseSearches: false,
            fastElementWordSearches: false,
            fastElementPhraseSearches: false,
            //add your other options here
        }
    );
    

    this is now a pure JavaScript example, was this what you were after?