Сравнение основных данных с элементами, присутствующими в XML

#xquery #marklogic

#xquery #marklogic

Вопрос:

 <MasterData>
  <Name>AA</Name>
  <EmpId>123</EmpId>
  <AccountNo>111</AccountNo>
   <IFSC>ABC</IFSC>
  <AccountData>
    <AccountNo>111</AccountNo>
    <IFSC>ABC</IFSC>
  </AccountData>
  <AccountData>
    <AccountNo>222</AccountNo>
    <IFSC>DEF</IFSC>
  </AccountData>
</MasterData>
 

У меня в базе данных есть такой XML, у меня есть требование проверить комбинацию AccountNo IFSC, присутствующую в MasterData (не в разделе AccountData), и сравнить со всеми документами, присутствующими в коллекции, и проверить, соответствует ли она данным, представленным в разделе AccountData, если их соответствие идентифицируетURI документа.
Сначала определите уникальную комбинацию AccountNo IFSC из раздела Masterdata, а затем проверьте, присутствует ли эта комбинация в каком-либо разделе AccountData, в этом xml есть другие элементы, кроме AccountNo и IFSC

Ответ №1:

Если у вас были индексы диапазона AccountNo IFSC для элементов и, то вы могли бы:

  1. извлеките набор значений из AccountNo , IFSC , и cts:uri-reference() с cts:value-tuples() помощью .
  2. создайте карту, используя составной ключ со значениями AccountNo и IFSC и URI в качестве значений для этих записей карты
  3. удалите любую запись, с которой связан только один URI
  4. возвращает карту, которая будет иметь набор URI, соответствующий каждой комбинации значений AccountNo и IFSC

Что-то вроде этого:

 let $accountNumber-IFSC := 
  cts:value-tuples(
    (
      cts:element-reference(xs:QName("AccountNo")), 
      cts:element-reference(xs:QName("IFSC")),
      cts:uri-reference()
    )
   )
let $map := map:new()
let $_create_map_value_to_uris := for $co-occurrence in $accountNumber-IFSC
let $key := concat($co-occurrence[1], " ", $co-occurrence[2])
let $value := (map:get($map, $key), $co-occurrence[3])
return map:put($map, $key, $value)

let $_prune_single_uri :=  
  for $key in map:keys($map)
  let $value := map:get($map, $key)
  where not(tail($value))
  return 
    map:put($map, $key, ())
  
return 
  $map
 

Если вам просто нужен список URI, вы можете инвертировать map: -$map и вернуть его ключи: return map:keys(-$map)

Если бы у вас был индекс диапазона EmpId , вы могли бы использовать его вместо URI документа.

Ответ №2:

Используя функции API Optic, вы можете сделать нечто подобное с индексами диапазона элементов:

 import module namespace op = "http://marklogic.com/optic" at "/MarkLogic/optic.xqy";

op:from-lexicons(
  map:entry("AccountNo", cts:element-reference(xs:QName("AccountNo"))) 
  => map:with("IFSC", cts:element-reference(xs:QName("IFSC")))
  => map:with("URI", cts:uri-reference())
)
=> op:group-by(
    ("IFSC", "AccountNo"), 
    (
      op:group-concat("URIs", "URI", map:entry("separator", ", ")), 
      op:count("count", op:col("URI"))
    )
  )
=> op:where(op:gt(op:col("count"), 1))
=> op:result()