2012-08-01 3 views
0

J'ai plusieurs documents xml employés enregistrés dans ML DB avec le doc uri (/employee/*.xml), je veux prendre la mise à jour du nouveau XML où la clé de référence unique est roleID (en ML XML son roleID et dans le nouveau XML c'est newroleID). Chaque fois qu'une correspondance est trouvée, elle doit mettre à jour la valeur firstName de ML xml avec newFirstName de new XMl, lastname avec newlastName, dep avec new dep et le reste de la structure xml doit rester identique.Mise à jour du noeud dans Marklogic DB

structure XML MarkLogic est comme suit:

doc uri /employee/1.xml 
    <employee> 
     <firstName>Jim</firstName> 
     <lastName>Day</lastName> 
     <dep>IT</dep> 
     <city>Boston</city> 
     <roleID>1111<roleID> 
     <internalID>2222</internalID> 
    </employee> 

    doc uri /employee/2.xml 
    <employee> 
     <firstName>Jan</firstName> 
     <lastName>Silly</lastName> 
     <dep>Finance</dep> 
     <city>DC</city> 
     <roleID>3333<roleID> 
     <internalID>4444</internalID> 
    </employee> 

    doc uri /employee/3.xml 
    <employee> 
     <firstName>Jack</firstName> 
     <lastName>John</lastName> 
     <dep>HR</dep> 
     <city>Virginia</city> 
     <roleID>5555<roleID> 
     <internalID>6666</internalID> 
    </employee> 

j'essaie cela, mais pas sûr comment mettre à jour le document, aussi doenst semble être optimisé XQuery, s'il vous plaît aider.

let $newXML := <employees> 
         <newemployee> 
          <NewfirstName>New Fname1</newfirstName> 
          <newlastName>New Lname1</newlastName> 
          <newdep>New Dep1</newdep> 
          <newcity>Boston</newcity> 
          <newroleID>1111<newroleID> 
          <internalID>2222</internalID> 
         </newemployee> 
         <newemployee> 
          <newfirstName>New Fname2</newfirstName> 
          <newlastName>New Lname</newlastName> 
          <newdep>New Dep</newdep> 
          <newcity>Boston</newcity> 
          <newroleID>5555<newroleID> 
          <newinternalID>6666</newinternalID> 
         </employee> 
        </employees> 
    for $oldXML in doc("/employee/*.xml")/employee 
     where $newXML/newemployee/newroleID eq $oldXML/roleID 
     return 
      for $Matched in $oldXML 
      return 
      let $finalXML := 
       (: Not sure how to update some nodes in given URI, where rest of structure remain same :) 

       <employee> 
        <firstName>{$newXML/newemployee/newfirstName/text()}</firstName> 
        <lastName>{$newXML/newemployee/newlastName/text()}</lastName> 
        <dep>{$newXML/newemployee/newdep/text()}</dep>    
       </employee> 

Répondre

3

Voir xdmp:node-replace

Dans l'exemple de la documentation:

(: insert the doc :) 
xdmp:document-insert("/example.xml", <a><b>bbb</b></a>); 
(: replace the b node in the doc with this c node :) 
xdmp:node-replace(doc("/example.xml")/a/b, <c>ccc</c>); 
doc("/example.xml") => <a><c>ccc</c></a> 
1

L'expression doc("/employee/*.xml") ne fonctionne pas. En utilisant xdmp:directory, à condition que le répertoire soit créé (automatiquement ou manuellement). Sinon, vous pouvez utiliser cts:uri-match pour trouver uris pour les employés, et passer un coup unique à doc(), à condition que le lexique URI soit activé.

Mais ... le plus gros goulot d'étranglement de votre approche est de parcourir TOUS les documents. Ce n'est pas nécessaire. Si roleID est unique, utilisez-le pour l'uri, vous n'aurez donc pas besoin de parcourir tous les docs, ouvrez-le immédiatement. Vous pouvez également utiliser une expression qui peut être optimisée par le processeur XQuery ou simplement utiliser des index. Quelque chose comme ce qui suit:

doc()[//roleID = $newRoleID] 

Ou:

cts:search(doc(), cts:element-value-query(xs:QName("roleID"), $newRoleID)) 

Pour la mise à jour elle-même, vous pouvez utiliser xdmp:node-replace et connexes comme suggéré par @sgarrett, mais vous pouvez aussi recréer simplement le XML entier, et utiliser xdmp : document-insert pour le remplacer entièrement. Le document est entièrement remplacé derrière la scène, de sorte que vous remarquerez à peine toute différence avec de si petits documents.

HTH!

+0

J'imagine que cts: search est plus rapide que faire doc() 'avec un prédicat, mais je peux me tromper. – sinemetu1

+1

@sgarrett dépend fortement si l'optimiseur voit qu'il peut être optimisé ou non. Peut-être besoin de jouer avec la syntaxe exacte. Des fonctions comme 'xdmp: plan' aident avec ça, mais le timing devrait en dire assez. Si elle est optimisée, la route XPath est aussi rapide que la route cts: search. Ils veulent dire exactement la même chose. – grtjn

+0

'xdmp: Le répertoire ("/employee/", $ depth)' ne nécessite * pas * de création de répertoire, ni manuel ni automatique. Il utilise l'index universel. Voir http://blakeley.com/blogofile/2012/03/19/directory-assistance/ – mblakele

Questions connexes