Xquery 如何在marklogic中获取2个集合之间的差异URI

Xquery 如何在marklogic中获取2个集合之间的差异URI,xquery,marklogic,Xquery,Marklogic,我有两个收藏 我需要根据文件名获取两个集合之间的差异uri 示例场景: Collection 1: /data/1.xml /data/2.xml /data/3.xml collection 2: /test/1.xml /test/2.xml /test/3.xml /test/4.xml /test/5.xml output: /data/1.xml /data/2.xml /data/3.xml /test/4.xml /test/5.xml 集合表示法: Delta:(产生

我有两个收藏

我需要根据文件名获取两个集合之间的差异uri

示例场景:

Collection 1:

/data/1.xml
/data/2.xml
/data/3.xml


collection 2:

/test/1.xml
/test/2.xml
/test/3.xml
/test/4.xml
/test/5.xml

output:
/data/1.xml
/data/2.xml
/data/3.xml
/test/4.xml
/test/5.xml
集合表示法:

Delta:(产生‘a’)

交叉口:(b,c)

对于其他两种排列,反向c1和c2

为了更好地阅读,请查看Dave Cassel的以下内容:

Delta:(产生‘a’)

交叉口:(b,c)

对于其他两种排列,反向c1和c2


为了更好地阅读,请查看Dave Cassel的这篇文章,按照David的建议使用set delta是正确的,但是您需要首先为URI生成文件名键。映射在这方面非常有用,这使得保持文件名键与其原始URI关联变得非常容易

首先生成两个带有文件名键和URI值的映射。然后,在映射键上使用set delta,生成一系列不同的文件名。然后从源映射中获取这些文件名的URI:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")
let $map-x := map:new($x ! map:entry(tokenize(., '/')[last()], .))
let $map-y := map:new($y ! map:entry(tokenize(., '/')[last()], .))
let $keys-diff-y := map:keys($map-y)[not(. = map:keys($map-x))]
let $diff-y := map:get($map-y, $keys-diff-y)
return ($x, $diff-y)

按照David的建议使用set delta是正确的,但是您需要首先为URI生成文件名键。映射在这方面非常有用,这使得保持文件名键与其原始URI关联变得非常容易

首先生成两个带有文件名键和URI值的映射。然后,在映射键上使用set delta,生成一系列不同的文件名。然后从源映射中获取这些文件名的URI:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")
let $map-x := map:new($x ! map:entry(tokenize(., '/')[last()], .))
let $map-y := map:new($y ! map:entry(tokenize(., '/')[last()], .))
let $keys-diff-y := map:keys($map-y)[not(. = map:keys($map-x))]
let $diff-y := map:get($map-y, $keys-diff-y)
return ($x, $diff-y)

两种备选解决方案:

第一种方法是,使用一致的键(最后一个斜杠后的子字符串)将每个项目放入映射中,然后为每个键选择映射中的第一个项目:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")
let $intersection := map:map()
let $_ := ($x, $y) ! ( 
  let $key := tokenize(., "/")[last()] 
  return 
    map:put($intersection, $key, (map:get($intersection, $key), .))
)
return 
  for $key in map:keys($intersection)
  for $uri in map:get($intersection, $key)[1]
  order by number(replace($uri, ".*/(\d+).xml", '$1'))
  return $uri
第二种方法是,确保仅为给定密钥设置第一项:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")

let $intersection := map:map()
let $_ := ($x, $y) ! ( 
  let $key := tokenize(., "/")[last()] 
  return 
    if (fn:exists(map:get($intersection, $key))) then ()
    else map:put($intersection, $key, .)
)
return 
  for $uri in map:get($intersection, map:keys($intersection))
  order by number(replace($uri, ".*/(\d+).xml", '$1'))
  return $uri

order by
是可选的,但使用地图时,键的顺序可能不一致。根据您的需要进行定制(即:首先是/data/uri,然后是/test/uri等),如果您不关心uri的顺序,则可将其删除。

两种替代解决方案:

第一种方法是,使用一致的键(最后一个斜杠后的子字符串)将每个项目放入映射中,然后为每个键选择映射中的第一个项目:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")
let $intersection := map:map()
let $_ := ($x, $y) ! ( 
  let $key := tokenize(., "/")[last()] 
  return 
    map:put($intersection, $key, (map:get($intersection, $key), .))
)
return 
  for $key in map:keys($intersection)
  for $uri in map:get($intersection, $key)[1]
  order by number(replace($uri, ".*/(\d+).xml", '$1'))
  return $uri
第二种方法是,确保仅为给定密钥设置第一项:

let $x := (
  "/data/1.xml",
  "/data/2.xml",
  "/data/3.xml")
let $y := (
  "/test/1.xml",
  "/test/2.xml",
  "/test/3.xml",
  "/test/4.xml",
  "/test/5.xml")

let $intersection := map:map()
let $_ := ($x, $y) ! ( 
  let $key := tokenize(., "/")[last()] 
  return 
    if (fn:exists(map:get($intersection, $key))) then ()
    else map:put($intersection, $key, .)
)
return 
  for $uri in map:get($intersection, map:keys($intersection))
  order by number(replace($uri, ".*/(\d+).xml", '$1'))
  return $uri

order by
是可选的,但使用地图时,键的顺序可能不一致。根据您的需要进行自定义(即:首先是/data/uri,然后是/test/uri等),或者如果您不关心uri的顺序,则删除它。

如果使用map:map,您可能会使用映射运算符:@grtjn映射运算符对键和值是否相同非常挑剔,因此无法在此处简单地使用减法运算符来执行差异,因为键是文件名,值是URI。如果使用map:map,您可能会使用映射运算符:@grtjn映射运算符对键和值是否相同非常挑剔,因此无法在此处简单地使用减法运算符来执行差异,因为键是文件名,值是URI。非常感谢..这对我非常有用。非常感谢..这对我非常有用。