Search code examples
javaxsltnosqlxquerymarklogic

XML node replace failure


I try Corb to search and update node in large number of documents:

Sample input:

<hcmt xmlns="http://horn.thoery">
  <susceptible>X</susceptible>
  <reponsible>foresee–intervention</reponsible>
  <intend>Benefit Protagonist</intend>
  <justified>Goal Outwiegen</justified>
</hcmt> 

Xquery:

(: let $resp   :=  "foresee–intervention" :)
 
let $docs :=    
  cts:search(doc(),
  cts:and-query((
  cts:collection-query("hcmt"),
  cts:path-range-query("/horn:hcmt/horn:responsible", "=", $resp)
        ))
    )
return
  for $doc in $docs
return
  xdmp:node-replace($doc/horn:hcmt/horn:responsible, "Foresee Intervention")

Expected output:

<hcmt xmlns="http://horn.thoery">
  <susceptible>X</susceptible>
  <reponsible>Foresee Intervention</reponsible>
  <intend>Benefit Protagonist</intend>
  <justified>Goal Outwiegen</justified>
</hcmt>

But node-replace didn’t happen in Corb and no error returns. Other queries work fine in Corb. How can the node-replace work correctly in Corb?

Thanks in advance for any help.


Solution

  • I create functions to reconcile the encoding matters. This not only mitigates potential API transaction failures but also is a requisite to validate & encode parameter or element/property/uri name.

    That said, a sample MarkLogic Java API implementation is:

    1. Create a dynamic query construct in the filesystem, in my case, product-query-option.xml (use the query value directly: Chooser–Option)
    <search xmlns="http://marklogic.com/appservices/search">
        <query>
            <and-query>
                <collection-constraint-query>
                    <constraint-name>Collection</constraint-name>
                    <uri>proto</uri>
                </collection-constraint-query>
                <range-constraint-query>
                    <constraint-name>ProductType</constraint-name>
                    <value>Chooser–Option</value>
                </range-constraint-query>
            </and-query>
        </query>
    </search>
    
    1. Deploy the persistent query options to modules database, in my case, search-lexis.xml, the options file is like:
    <options xmlns="http://marklogic.com/appservices/search">
         <constraint name="Collection">
             <collection prefix=""/>
         </constraint>
         <constraint name="ProductType">
            <range type="xs:string" collation="http://marklogic.com/collation/en/S1">
              <path-index xmlns:prod="schema://fc.fasset/product">/prod:requestProduct/prod:_metaData/prod:productType</path-index>
            </range>
         </constraint>
    </options>
    
    1. Follow on from Dynamic Java Search
            File file = new File("src/main/resources/queryoption/product-query-option.xml");
    
            FileHandle fileHandle = new FileHandle(file);
    
            RawCombinedQueryDefinition rcqDef = queryMgr.newRawCombinedQueryDefinition(fileHandle, queryOption);
    
    • You can, assuredly, combine the query and the options as one handle in QueryDefinition.
    1. Your original node-replace is translated as Java Partial Update
    • make sure the DocumentPatchBuilder setNamespaces with the correct NamespaceContext.
    1. For batch data operation, the performant approach is MarkLogic Data Movement: instantiate the QueryBatcher with the searched Uris, supply the replace value or data fragment PatchBuilder.replaceValue , and complete the batch with dbClient.newXMLDocumentManager().patch(uri, patchHandle);

    MarkLogic Data Services: If you succeed above, perhaps, then go at a more robust and scalable enterprise SOA approach, please review Data Services.

    • The implementation with Gradle is like:

    Data Services Implementations

    (Note, all of the transformation metrics should be parameters, including path/element/property name, namespace, value…etc. Nothing is hardcoded.) One proxy service declared in service.json can serve multiple end points (under /root/df-ds/fxd ) with different types of modules which give you the free rein to develop pure Java or extend the development platform to handle complex data operations.

    If these operations are persistent node update, you should consider in-memory node transform before the ingestion. Besides the MarkLogic data transformation tools, you can harness the power of XSLT2+.

    Saxon XPathFactory could be a serviceable vehicle to query/transform node. Not sure if it is a reciprocity, ML Java API implements the XPath compile to split large paths and stream transaction. XSLT/Saxon is not my forte; therefore, I can’t comment how comparable it is with this encode/decode particularity or how it handles transaction (insert, update…etc) streaming.