0

I've been working through a tutorial to build a rest service with marklogic. I've built a simple example through using roxy deploy tool and calling ml ext . My problem is trying to grab a specific element out of a document via rest call. Here is what i have so far:

    declare
%roxy:params("dataType=xs:string","pNumber=xs:number", "sNumber=xs:string", "searchTerm=xs:string")
function jad:get(
  $context as map:map,
  $params  as map:map
) as document-node()*
{
  map:put($context, "output-types", "application/xml"),
  map:put($context, "accept-types", "multipart/mixed"),
  map:put($context, "output-status", (200, "OK")),
  let $doc := doc('testNew.xml')
  let $docs := $doc//stuff/pData/sData/headerData/bData/sitData[contains(., 'word')]
  let $c := json:config("custom"),

   $_ := map:put($c,"whitespace", "ignore"),
   $_ := map:put( $c , "camel-case" , fn:true() )
   let $results := search:search("word",
   <options xmlns="http://marklogic.com/appservices/search">
     <transform-results apply="raw"/>
   </options>)
return document{$doc//stuff/pData/sData/headerData/bData/sitData[contains(., 'word')]}

this has gone through many iterations but ultimately the problem is I can't seem to simply return a document along an xpath within rest. When I call upon this url I get an error like this:

enter image description here

After reading through many stackoverflow links this seems to stem from the Xpath only returning a snippet. The problem is I don't know how to return the full results. I had read somewhere that I could set a property somewhere in my "rest-api" folder to be but this hasn't stopped this problem. So what I would ultimately like is the possibility to search a specific document's internal structure for keywords.

EDIT: would I be better off using RXQ for this purpose?

Joshhw
  • 202
  • 2
  • 14
  • 1
    I think the culprit is not the fact that you are returning a snippet of xml, but the fact you potentially embed multiple snippets into one document node which would be invalid XML. Wrap the XPath from $doc till after the predicate with `(..)[1]` to pick only first sitData that matches to verify this idea. If that helps, take a step back, and think about how you would like to handle multiple matches.. – grtjn Mar 16 '17 at 19:29
  • @grtjn so that's what I'm trying to figure out. If I want to search a specific document in the database I'm not sure how to accomplish that without using xpath and if I have multiple xml snippets from the document, how can I just send them along as a single document. – Joshhw Mar 16 '17 at 19:36

1 Answers1

1

Based on your comments:

If I want to search a specific document in the database I'm not sure how to accomplish that without using xpath

If you know the URI of the document you want to return, you can get that one with fn:doc($uri).

if I have multiple xml snippets from the document, how can I just send them along as a single document

This should do it:

let $results := search:search("word",
  <options xmlns="http://marklogic.com/appservices/search">
    <transform-results apply="raw"/>
  </options>)
return document { $results }

search:search returns a single XML element; you need to return a document-node, so I've wrapped the search results in document { }.

If you wanted to return multiple elements, you'll need to enclose them in a single parent, as an XML document may only have one root:

return document{
  <root>{
    $doc//stuff/pData/sData/headerData/bData/sitData[contains(., 'word')]
  }</root>
}

Also, looking at your HTTP call:

http://localhost:8040/v1/resources/decosta?dataType=thing&policyNumber=1234&searchTerm=thisthingrighthere

Parameters for REST API extensions are required to have an "rs:" prefix on them, to distinguish from parameters for the REST API itself. So your URL should look like this:

http://localhost:8040/v1/resources/decosta?rs:dataType=thing&rs:policyNumber=1234&rs:searchTerm=thisthingrighthere

In your extension, you can then access the parameters like this:

let $data-type := map:get($params, "dataType")
Dave Cassel
  • 8,352
  • 20
  • 38
  • Hey Dave, thanks so much for responding, your videos have helped me along to this point. My question is would constraints be a good path to go down if I want to only select certain documents that fit my search criteria? – Joshhw Mar 16 '17 at 20:34
  • From the look of your parameters, probably yes, you want constraints. I'm guessing that policyNumber matches up with an element or attribute. That's easily done with [a value constraint](http://docs.marklogic.com/guide/search-dev/appendixa#id_52778). The same approach likely will work for dataType. For searchTerm, that can be the "q" parameter passed to [/v1/search](http://docs.marklogic.com/REST/GET/v1/search). You can configure search options with Roxy -- see ${project-home}/rest-api/config/options/all.xml. – Dave Cassel Mar 16 '17 at 20:51
  • glad the videos were helpful! – Dave Cassel Mar 16 '17 at 20:51
  • 1
    You might also want to take a look at the extract-document-data query option. You might be able to get ML to narrow the output down to the parts of the matched documents that you want to return. http://docs.marklogic.com/guide/search-dev/query-options#id_37692. – kcoleman Mar 18 '17 at 14:52