Wednesday, August 18, 2010

How to check if the xml node exists or variable has a null value in xquery

 

There are three ways you can do it.

1) fn:exists(argument as item()*) – if argument returns empty then its false otherwise true.

for eg.

-----------

fn:exists(xdmp:eval(“1+1”))

returns true.

------------

fn:exists(xdmp:eval(“”))

returns false.

-------------

declare variable $var := <node><elem></elem></node>;

fn:exists($var//elem)

returns true.

fn:exists($var//para)

returns false.

-----------------

 

2) xdmp:exists(searchable-expression as item()*) – returns true if the result of the expression is xpath node()*

for eg.

xdmp:exists(fn:doc())

 

3) If (expression) - use if statement to check if the xpath returns a result.

 

for eg.

declare variable $var := <node><elem></elem></node>;

if($var//elem)

then <result>$var//elem/@value</result>

else <result>empty</result>

Calling/Sending Parameters to Xquery & Best Practice

 

To call an xquery stored in a file, you can use xdmp:invoke function.

you need to specify the file name and the parameters to send.

syntax

xdmp:invoke(
filepath as xs:string
[params as item()*]
[options as node()?]
) as item()*

for eg.

Invoking xquery file with parameters

xdmp:invoke("xqueryfilename.xqy", (xs:QName("parameter name1"), "parameter value",xs:QName("parameter name2"), "parameter value”))

Invoking xquery file without parameters

xdmp:invoke("xqueryfilename.xqy")

 

Invoking xquery file with a URI and namespace

Xquery file at URI http://marklogicsite.com/modules with filename xqueryfilename.xqy

Note – options should always be in xdmp:eval namespace

---------------------------------------------------

 xquery version "1.0-ml";
declare namespace exns="example-namespace";
declare variable $exns:docuriparam as xs:string external;
fn:doc($exns:docuriparam)


---------------------------------------------------



It returns the document with the specified path.



---------------------------------------------------



xquery version "1.0-ml";
declare namespace exns="example-namespace";


xdmp:invoke("xqueryfilename.xqy",(xs:QName(“exns:docuriparam”), “modulename/xmldocname.xml”) , <options xmlns=”xdmp:eval”><modules>{xdmp:modules-database()}</modules><root>http://marklogicsite.com/modules</root></options>)



----------------------------------------------------



Here xdmp:modules-database() returns the ID of the modules database.



root is for root path of the modules. To return the current root path use xdmp:modules-root()



 



Best Practice regarding passing parameters to xquery.



If the xquery requires several parameters to be sent, its better to fragment all the parameters inside a single XML Node which in turn will get passed as a parameter. The xquery then in turn will process the node and xpath to get the parameter as and when required.



 



For eg. consider the following variables declaration in xquery.



-----------------------------------



xquery version "1.0-ml";



declare variable $employeeName as xs:string external;



declare variable $companyName as xs:string external;



declare variable $departmentName as xs:string external;



declare variable $registered as xs:string external;



declare variable $dateLastAccessed as xs:string external;



-----------------------------------



We can modify the above and use a single parameter to get all the details sought



-----------------------------------



xquery version "1.0-ml";



declare variable $parameters as xs:string external;


-----------------------------------

and the parameter value could be



-----------------------------------



<parameters>

<parameter><employeeName>empname</employeeName></parameter>


<parameter><companyName>compname</companyName></parameter>


<parameter><departmentName>dname</departmentName></parameter>


<parameter><registered>Yes</sortparam></registered>


<parameter><dateLastAccessed>2006-05-05</dateLastAccessed></parameter>


</parameters>



-----------------------------------



In the xquery you can xpath $parameters to get your value



for eg. $parameters//employeeName will get you the value of first parameter.



 



This makes the code better and passing the parameters will be clean and nice.

Tuesday, August 17, 2010

Spelling suggestions with Marklogic

 

When you search a word in Youtube and if Youtube takes it as misspelled then it returns a “Did you mean: suggested keyword” suggestion. Marklogic too provides spell suggestion words that you can use in your application.

Marklogic provides two functions relating to spelling correction.

1) spell:suggest() – To return a set of correct spellings for the word entered.

2) spell:suggest-detailed() – To return a set of elements describing each suggestion, including the suggested word, the distance, the key distance, the word distance, and the levenshtein distance.

You will use spell:suggest() to get the suggested words unless you want to compare the properties of the returned suggested words for which you will use spell:suggest-detailed()

To return a correct spelling of the given word, use

spell:suggest("spellingDictionary.xml","keyword")


It will return all the words which are close to keyword entered.


Here spellingDictionary.xml is a dictionary file that contains all the spellings.


The format of the dictionary is


<dictionary xmlns="http://marklogic.com/xdmp/spell">


<metadata>


</metadata>


<word></word>


<word></word>


......


</dictionary>



you may either create your own dictionary or download the dictionary provided by marklogic at http://github.com/marklogic/dictionaries/tree/master/dictionaries/


You may also edit the dictionary provided by marklogic and add/delete words in element <word></word>.


for a search query “welcme compter” you may use the below xquery to return spelling suggestions.


---------


declare variable $spellWords := <words><word>welcme</word><word>compter</word></words>;


<spellcheckerResult>

{


for $word in $spellWords//*:word


return  spell:suggest("/dictionary/large-dictionary.xml", $word)[1]


}


</spellcheckerResult>




----------


RESULT


<spellcheckerResult>welcome computer</spellcheckerResult>


spell:suggest returns a sequence of suggestion words. The first([1]) word returned is of the most closest one. so use “[1]” to  return the first closest word.


If word is correct then the same word will be returned for eg.


declare variable $spellWords := <words><word>welcome</word><word>compter</word></words>;


result would be


<spellcheckerResult>welcome computer</spellcheckerResult>



Suggestions with search:search api - Marklogic Server

 

Api search:suggest is used to return suggestions that match a wildcard string.

syntax :-


search:suggest(

qtext as xs:string+


[options as element(opt:options)?]


[limit as xs:unsignedInt?]


[cursor-position as xs:unsignedInt?]


[focus as xs:positiveInteger?]


) as xs:string*



Keyword Suggestion in Marklogic can be used in two ways.



1) Query suggestions - By Async call to search:suggest for each key pressed in the textbox. This would fill the combo box with the suggested keywords to select as you see in Google or YouTube.


2) You may also go for:suggested words – you search your keywords and along with the search results you see some suggestions. 


you can define your suggestion source as an existing element 


Configure default-suggestion-source option for the suggestions.



<default-suggestion-source>
<samplecollection/>
</default-suggestion-source>


samplecollection can be existing named constraint, value, word or range element/attribute.


for eg.


Range element


<default-suggestion-source>
<range type="xs:date">
<element ns="samplenamespace" name="book"/>
<attribute ns="" name="publishDate"/>
</range>
</default-suggestion-source>


Word lexicon


<default-suggestion-source>
<word>
<field name="bookdata"/>
</word>
</default-suggestion-source>


 


If default-suggestion-source element is empty then the constraint or operator(if specified) in the options will be considered by default else it would return empty sequence.


Monday, August 16, 2010

xquery to return a document

 

You may use below queries to return document(s) in marklogic server.

fn:doc() or doc()

Returns all the documents in the database

To return the first document

fn:doc()[1]

To return specific document(s) with a known URI

USE

fn:doc(
[uri as xs:string*]
) as document-node()*

xs:string* –>  URI(s) of the document to retrieve.

for eg.

1) To return document having URI “/sample/mydoc.xml”

fn:doc(“/sample/mydoc.xml”)


2) To return documents having URI “/sample/mydoc1.xml” and “/sample/mydoc2.xml”



fn:doc((“/sample/mydoc1.xml”, “/sample/mydoc2.xml”))


 


fn:collection() – Returns all the documents in the database



To return the first document in the collection



fn:collection()[1]



fn:collection(

[uri as xs:string*]


) as document-node()*



xs:string* –>  a list of URIs or collection name



returns all of the documents in the collection as document-node()*.



for eg.


fn:collection(“collectionName”)




A simple Xquery file to return a document with the URI coming from external parameter.



-----------------------------------------



xquery version "1.0-ml";



declare namespace ns1= "http://www.examplenamespace.com/ns1";





declare variable $externparameter as xs:string external;



<document>

{


fn:doc($externparameter)


}


</document>



----------------------------------------------